earthdata-mcp-server 0.5.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.
Files changed (32) hide show
  1. earthdata_mcp_server-0.5.0/.github/workflows/build.yaml +88 -0
  2. earthdata_mcp_server-0.5.0/.github/workflows/release.yaml +108 -0
  3. earthdata_mcp_server-0.5.0/.gitignore +126 -0
  4. earthdata_mcp_server-0.5.0/.licenserc.yaml +18 -0
  5. earthdata_mcp_server-0.5.0/.pre-commit-config.yaml +38 -0
  6. earthdata_mcp_server-0.5.0/CHANGELOG.md +24 -0
  7. earthdata_mcp_server-0.5.0/Dockerfile +18 -0
  8. earthdata_mcp_server-0.5.0/LICENSE +29 -0
  9. earthdata_mcp_server-0.5.0/Makefile +81 -0
  10. earthdata_mcp_server-0.5.0/PKG-INFO +292 -0
  11. earthdata_mcp_server-0.5.0/README.md +233 -0
  12. earthdata_mcp_server-0.5.0/RELEASE.md +62 -0
  13. earthdata_mcp_server-0.5.0/dev/README.md +9 -0
  14. earthdata_mcp_server-0.5.0/dev/content/README.md +9 -0
  15. earthdata_mcp_server-0.5.0/dev/content/notebook.ipynb +33 -0
  16. earthdata_mcp_server-0.5.0/docs/authentication.md +17 -0
  17. earthdata_mcp_server-0.5.0/docs/download.md +61 -0
  18. earthdata_mcp_server-0.5.0/earthdata_mcp_server/__init__.py +10 -0
  19. earthdata_mcp_server-0.5.0/earthdata_mcp_server/__main__.py +6 -0
  20. earthdata_mcp_server-0.5.0/earthdata_mcp_server/__version__.py +7 -0
  21. earthdata_mcp_server-0.5.0/earthdata_mcp_server/examples/README.md +54 -0
  22. earthdata_mcp_server-0.5.0/earthdata_mcp_server/examples/__init__.py +3 -0
  23. earthdata_mcp_server-0.5.0/earthdata_mcp_server/examples/workflow_example.py +54 -0
  24. earthdata_mcp_server-0.5.0/earthdata_mcp_server/extension.py +445 -0
  25. earthdata_mcp_server-0.5.0/earthdata_mcp_server/server.py +105 -0
  26. earthdata_mcp_server-0.5.0/earthdata_mcp_server/tests/README.md +57 -0
  27. earthdata_mcp_server-0.5.0/earthdata_mcp_server/tests/__init__.py +1 -0
  28. earthdata_mcp_server-0.5.0/earthdata_mcp_server/tests/test_cli_options.py +20 -0
  29. earthdata_mcp_server-0.5.0/earthdata_mcp_server/tests/test_extension.py +210 -0
  30. earthdata_mcp_server-0.5.0/earthdata_mcp_server/tests/test_served_over_http.py +31 -0
  31. earthdata_mcp_server-0.5.0/pyproject.toml +113 -0
  32. earthdata_mcp_server-0.5.0/smithery.yaml +12 -0
@@ -0,0 +1,88 @@
1
+ # Copyright (c) 2023-2026 Datalayer, Inc.
2
+ # Distributed under the terms of the BSD 3-Clause License.
3
+
4
+ # Lint, type-check and test on every push and pull request, then build the
5
+ # distributions a release would publish and check them — so a tag never finds
6
+ # out first that the package does not build.
7
+
8
+ name: Build
9
+
10
+ on:
11
+ push:
12
+ branches:
13
+ - main
14
+ - 'feat/**'
15
+ pull_request:
16
+
17
+ concurrency:
18
+ group: build-${{ github.ref }}
19
+ cancel-in-progress: true
20
+
21
+ permissions:
22
+ contents: read
23
+
24
+ jobs:
25
+ lint:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ - uses: actions/setup-python@v5
30
+ with:
31
+ python-version: '3.12'
32
+ - name: Install
33
+ run: |
34
+ python -m pip install --upgrade pip
35
+ python -m pip install -e ".[lint,typing,test]"
36
+ - name: Ruff
37
+ run: ruff check earthdata_mcp_server
38
+ - name: MyPy
39
+ run: mypy earthdata_mcp_server
40
+
41
+ test:
42
+ runs-on: ubuntu-latest
43
+ strategy:
44
+ fail-fast: false
45
+ matrix:
46
+ python-version: ['3.10', '3.11', '3.12', '3.13']
47
+ steps:
48
+ - uses: actions/checkout@v4
49
+ - uses: actions/setup-python@v5
50
+ with:
51
+ python-version: ${{ matrix.python-version }}
52
+ - name: Install
53
+ run: |
54
+ python -m pip install --upgrade pip
55
+ python -m pip install -e ".[test]"
56
+ - name: Test
57
+ run: pytest -q
58
+
59
+ build:
60
+ runs-on: ubuntu-latest
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+ - uses: actions/setup-python@v5
64
+ with:
65
+ python-version: '3.12'
66
+ - name: Build the distributions
67
+ run: |
68
+ set -euo pipefail
69
+ python -m pip install --upgrade pip build twine
70
+ python -m build --sdist --wheel --outdir dist .
71
+ twine check --strict dist/*
72
+ - name: Install the wheel and find the extension
73
+ run: |
74
+ set -euo pipefail
75
+ python -m pip install dist/*.whl
76
+ cd "$RUNNER_TEMP"
77
+ python -c "
78
+ from reactor_mcp_server import build_host, load_extensions, parse_selection
79
+ host = build_host(load_extensions(['earthdata']))
80
+ tools = host.build(parse_selection('earthdata')).tool_names
81
+ assert 'search_earth_datasets' in tools, tools
82
+ print('earthdata extension discovered:', tools)
83
+ "
84
+ earthdata-mcp-server start --help
85
+ - uses: actions/upload-artifact@v4
86
+ with:
87
+ name: dist
88
+ path: dist/*
@@ -0,0 +1,108 @@
1
+ # Copyright (c) 2023-2026 Datalayer, Inc.
2
+ # Distributed under the terms of the BSD 3-Clause License.
3
+
4
+ # Publishes the release a tag names to PyPI, with no stored token: PyPI
5
+ # trusts this workflow file (OIDC trusted publishing, through the `pypi`
6
+ # environment). The tag must name the version in earthdata_mcp_server/__version__.py; a
7
+ # version already published is skipped. See RELEASE.md.
8
+
9
+ name: Release
10
+
11
+ on:
12
+ push:
13
+ tags:
14
+ - 'v*'
15
+
16
+ concurrency:
17
+ group: release-${{ github.ref }}
18
+ cancel-in-progress: false
19
+
20
+ permissions:
21
+ contents: read
22
+
23
+ jobs:
24
+ build:
25
+ runs-on: ubuntu-latest
26
+ outputs:
27
+ python: ${{ steps.plan.outputs.python }}
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: '3.12'
34
+
35
+ - name: Check the tag names the version the package carries
36
+ run: |
37
+ set -euo pipefail
38
+ tag="${GITHUB_REF_NAME#v}"
39
+ version="$(python -c "import re;print(re.search(r'__version__\s*=\s*[\"\']([^\"\']+)', open('earthdata_mcp_server/__version__.py').read())[1])")"
40
+ echo "tag=$tag version=$version"
41
+ test "$tag" = "$version"
42
+
43
+ - name: Find whether it is published yet
44
+ id: plan
45
+ run: |
46
+ set -euo pipefail
47
+ version="${GITHUB_REF_NAME#v}"
48
+ status="$(curl -sL -o /dev/null -w '%{http_code}' "https://pypi.org/pypi/earthdata-mcp-server/$version/json")"
49
+ if [ "$status" = "200" ]; then
50
+ echo "PyPI: earthdata-mcp-server $version is already published, skipping"
51
+ echo "python=" >> "$GITHUB_OUTPUT"
52
+ else
53
+ echo "PyPI: earthdata-mcp-server $version will be published"
54
+ echo "python=yes" >> "$GITHUB_OUTPUT"
55
+ fi
56
+
57
+ - name: Build
58
+ if: steps.plan.outputs.python != ''
59
+ run: |
60
+ set -euo pipefail
61
+ python -m pip install --upgrade pip build
62
+ python -m build --sdist --wheel --outdir dist .
63
+ ls -la dist
64
+
65
+ - uses: actions/upload-artifact@v4
66
+ if: steps.plan.outputs.python != ''
67
+ with:
68
+ name: python
69
+ path: dist/*
70
+
71
+ pypi:
72
+ needs: build
73
+ if: needs.build.outputs.python != ''
74
+ runs-on: ubuntu-latest
75
+ environment: pypi
76
+ permissions:
77
+ id-token: write
78
+ steps:
79
+ - uses: actions/download-artifact@v4
80
+ with:
81
+ name: python
82
+ path: dist
83
+ - uses: pypa/gh-action-pypi-publish@release/v1
84
+ with:
85
+ skip-existing: true
86
+
87
+ release:
88
+ name: GitHub release
89
+ needs: [build, pypi]
90
+ # Only after a publish that succeeded, or one skipped because the version is
91
+ # already on PyPI — never after one that failed or was cancelled, or the
92
+ # release would link to a version that does not exist.
93
+ if: always() && needs.build.result == 'success' && (needs.pypi.result == 'success' || needs.pypi.result == 'skipped')
94
+ runs-on: ubuntu-latest
95
+ permissions:
96
+ contents: write
97
+ steps:
98
+ - uses: actions/checkout@v4
99
+ with:
100
+ fetch-depth: 0
101
+ - name: Create the release with generated notes
102
+ run: |
103
+ version="${GITHUB_REF_NAME#v}"
104
+ gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1 && exit 0
105
+ gh release create "$GITHUB_REF_NAME" --title "Release $version" --generate-notes \
106
+ --notes "- [PyPI earthdata-mcp-server](https://pypi.org/project/earthdata-mcp-server/$version/)"
107
+ env:
108
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,126 @@
1
+ *.egg-info/
2
+ .ipynb_checkpoints
3
+
4
+ # Created by https://www.gitignore.io/api/python
5
+ # Edit at https://www.gitignore.io/?templates=python
6
+
7
+ ### Python ###
8
+ # Byte-compiled / optimized / DLL files
9
+ __pycache__/
10
+ *.py[cod]
11
+ *$py.class
12
+
13
+ # C extensions
14
+ *.so
15
+
16
+ # Distribution / packaging
17
+ .Python
18
+ build/
19
+ dist/
20
+ downloads/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ pip-wheel-metadata/
28
+ share/python-wheels/
29
+ .installed.cfg
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Environment variables:
59
+ .env
60
+
61
+ # Scrapy stuff:
62
+ .scrapy
63
+
64
+ # Sphinx documentation
65
+ docs/_build/
66
+
67
+ # PyBuilder
68
+ target/
69
+
70
+ # pyenv
71
+ .python-version
72
+
73
+ # celery beat schedule file
74
+ celerybeat-schedule
75
+
76
+ # SageMath parsed files
77
+ *.sage.py
78
+
79
+ # Spyder project settings
80
+ .spyderproject
81
+ .spyproject
82
+
83
+ # Rope project settings
84
+ .ropeproject
85
+
86
+ # Mr Developer
87
+ .mr.developer.cfg
88
+ .project
89
+ .pydevproject
90
+
91
+ # mkdocs documentation
92
+ /site
93
+
94
+ # mypy
95
+ .mypy_cache/
96
+ .dmypy.json
97
+ dmypy.json
98
+
99
+ # ruff
100
+ .ruff_cache
101
+
102
+ # Pyre type checker
103
+ .pyre/
104
+
105
+ # End of https://www.gitignore.io/api/python
106
+
107
+ # OSX files
108
+ .DS_Store
109
+
110
+ # Include
111
+ !**/.*ignore
112
+ !**/.*rc
113
+ !**/.*rc.js
114
+ !**/.*rc.json
115
+ !**/.*rc.yml
116
+ !**/.*config
117
+ !*.*rc.json
118
+ !.github
119
+ !.devcontainer
120
+
121
+ untracked_notebooks/*
122
+ .jupyter_ystore
123
+ .jupyter_ystore.db
124
+ docs/.yarn/*
125
+
126
+ uv.lock
@@ -0,0 +1,18 @@
1
+ header:
2
+ license:
3
+ content: |
4
+ Copyright (c) 2023-2024 Datalayer, Inc.
5
+
6
+ BSD 3-Clause License
7
+
8
+
9
+ paths-ignore:
10
+ - '**/*.ipynb'
11
+ - '**/*.json'
12
+ - '**/*.yaml'
13
+ - '**/*.yml'
14
+ - '**/.*'
15
+ - 'docs/**/*'
16
+ - 'LICENSE'
17
+
18
+ comment: on-failure
@@ -0,0 +1,38 @@
1
+ ci:
2
+ autoupdate_schedule: monthly
3
+
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: v5.0.0
7
+ hooks:
8
+ - id: end-of-file-fixer
9
+ - id: check-case-conflict
10
+ - id: check-executables-have-shebangs
11
+ - id: requirements-txt-fixer
12
+ - id: check-added-large-files
13
+ - id: check-case-conflict
14
+ - id: check-toml
15
+ - id: check-yaml
16
+ - id: debug-statements
17
+ - id: forbid-new-submodules
18
+ - id: check-builtin-literals
19
+ - id: trailing-whitespace
20
+
21
+ - repo: https://github.com/python-jsonschema/check-jsonschema
22
+ rev: 0.29.4
23
+ hooks:
24
+ - id: check-github-workflows
25
+
26
+ - repo: https://github.com/executablebooks/mdformat
27
+ rev: 0.7.19
28
+ hooks:
29
+ - id: mdformat
30
+ additional_dependencies:
31
+ [mdformat-gfm, mdformat-frontmatter, mdformat-footnote]
32
+
33
+ - repo: https://github.com/charliermarsh/ruff-pre-commit
34
+ rev: v0.8.0
35
+ hooks:
36
+ - id: ruff
37
+ args: ["--fix"]
38
+ - id: ruff-format
@@ -0,0 +1,24 @@
1
+ <!--
2
+ ~ Copyright (c) 2023-2024 Datalayer, Inc.
3
+ ~
4
+ ~ BSD 3-Clause License
5
+ -->
6
+
7
+ # Changelog
8
+
9
+ ## 0.5.0
10
+
11
+ - The server is now a [`reactor_mcp_server`](https://pypi.org/project/reactor-mcp-server/)
12
+ extension. Installed beside any host of that foundation, it is discovered on the
13
+ `reactor.mcp.extensions` entry-point group and served as the opt-in `earthdata`
14
+ toolset (`/mcp?earthdata`). `earthdata-mcp-server start` still serves it on its
15
+ own, over stdio or streamable HTTP.
16
+ - Requires the MCP Python SDK 2 (`mcp>=2,<3`) and `reactor_mcp_server>=1.0.4`.
17
+ - Every tool carries its annotations: the searches are read-only, and all three are
18
+ idempotent and open-world.
19
+ - The tools no longer block the event loop: earthaccess runs in a worker thread.
20
+ - `search_earth_datasets` works with earthaccess 0.19, which turned `abstract`, `data_type` and
21
+ `landing_page` into properties; it failed on a fresh install before.
22
+ - `start` takes `--host`.
23
+ - Releases are cut by pushing a `vX.Y.Z` tag, published to PyPI through trusted
24
+ publishing. See RELEASE.md.
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2023-2026 Datalayer, Inc.
2
+ #
3
+ # BSD 3-Clause License
4
+
5
+ FROM python:3.12-slim
6
+
7
+ WORKDIR /app
8
+
9
+ COPY pyproject.toml LICENSE README.md ./
10
+ COPY earthdata_mcp_server/ earthdata_mcp_server/
11
+
12
+ RUN pip install --no-cache-dir .
13
+
14
+ EXPOSE 4040
15
+
16
+ # stdio by default; `start --transport streamable-http` serves /mcp on 4040.
17
+ ENTRYPOINT ["earthdata-mcp-server"]
18
+ CMD ["start"]
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Datalayer
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,81 @@
1
+ # Copyright (c) 2023-2024 Datalayer, Inc.
2
+ #
3
+ # BSD 3-Clause License
4
+
5
+ SHELL=/bin/bash
6
+
7
+ .DEFAULT_GOAL := default
8
+
9
+ .PHONY: clean build test lint release
10
+
11
+ # The package version, read from the one place it is written.
12
+ VERSION = $(shell python -c "import re;print(re.search(r'__version__ = \"(.+)\"', open('earthdata_mcp_server/__version__.py').read())[1])")
13
+
14
+ default: all ## Default target is all.
15
+
16
+ help: ## display this help.
17
+ @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
18
+
19
+ all: clean dev ## Clean Install and Build
20
+
21
+ install:
22
+ pip install .
23
+
24
+ dev:
25
+ pip install -e ".[test,lint,typing]"
26
+
27
+ test: ## run the tests
28
+ pytest -q
29
+
30
+ lint: ## ruff and mypy, as CI runs them
31
+ ruff check earthdata_mcp_server
32
+ mypy earthdata_mcp_server
33
+
34
+ build:
35
+ pip install build
36
+ python -m build .
37
+
38
+ clean: ## clean
39
+ git clean -fdx
40
+
41
+ build-docker:
42
+ docker buildx build --platform linux/amd64,linux/arm64 -t datalayer/earthdata-mcp-server:${VERSION} .
43
+ docker image tag datalayer/earthdata-mcp-server:${VERSION} datalayer/earthdata-mcp-server:latest
44
+
45
+ push-docker:
46
+ docker push datalayer/earthdata-mcp-server:${VERSION}
47
+ docker push datalayer/earthdata-mcp-server:latest
48
+
49
+ pull-docker:
50
+ docker pull datalayer/earthdata-mcp-server:latest
51
+
52
+ claude-linux:
53
+ NIXPKGS_ALLOW_UNFREE=1 nix run github:k3d3/claude-desktop-linux-flake \
54
+ --impure \
55
+ --extra-experimental-features flakes \
56
+ --extra-experimental-features nix-command
57
+
58
+ jupyterlab:
59
+ pip uninstall -y pycrdt datalayer_pycrdt
60
+ pip install datalayer_pycrdt
61
+ jupyter lab \
62
+ --port 8888 \
63
+ --ip 0.0.0.0 \
64
+ --ServerApp.root_dir ./dev/content \
65
+ --IdentityProvider.token MY_TOKEN
66
+
67
+ start: ## start the earthdata mcp server with streamable-http transport
68
+ @exec echo
69
+ @exec echo MCP server endpoint: http://localhost:4040/mcp
70
+ @exec echo
71
+ @exec echo Define this endpoint in your MCP client configuration
72
+ @exec echo
73
+ earthdata-mcp-server start \
74
+ --transport streamable-http \
75
+ --port 4040
76
+
77
+ release: ## tag the version in __version__.py; the Release workflow publishes it
78
+ @test -z "$$(git status --porcelain)" || (echo "The working tree is not clean" && exit 1)
79
+ git tag -a v$(VERSION) -m "Release $(VERSION)"
80
+ @echo
81
+ @echo "Push the tag to publish: git push origin v$(VERSION)"