pwpush-mcp 0.2.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 (37) hide show
  1. pwpush_mcp-0.2.0/.env.example +45 -0
  2. pwpush_mcp-0.2.0/.github/dependabot.yml +26 -0
  3. pwpush_mcp-0.2.0/.github/workflows/ci.yml +43 -0
  4. pwpush_mcp-0.2.0/.github/workflows/pypi.yml +50 -0
  5. pwpush_mcp-0.2.0/.github/workflows/release.yml +91 -0
  6. pwpush_mcp-0.2.0/.gitignore +31 -0
  7. pwpush_mcp-0.2.0/.pre-commit-config.yaml +26 -0
  8. pwpush_mcp-0.2.0/CHANGELOG.md +55 -0
  9. pwpush_mcp-0.2.0/CONTRIBUTING.md +65 -0
  10. pwpush_mcp-0.2.0/Dockerfile +30 -0
  11. pwpush_mcp-0.2.0/LICENSE +21 -0
  12. pwpush_mcp-0.2.0/PKG-INFO +223 -0
  13. pwpush_mcp-0.2.0/README.md +190 -0
  14. pwpush_mcp-0.2.0/SUPPORT.md +37 -0
  15. pwpush_mcp-0.2.0/UPGRADING.md +35 -0
  16. pwpush_mcp-0.2.0/catalog/metadata.json +1 -0
  17. pwpush_mcp-0.2.0/catalog/readme.md +39 -0
  18. pwpush_mcp-0.2.0/catalog/server.yaml +61 -0
  19. pwpush_mcp-0.2.0/compose.yml +12 -0
  20. pwpush_mcp-0.2.0/pyproject.toml +87 -0
  21. pwpush_mcp-0.2.0/scripts/gen_metadata.py +93 -0
  22. pwpush_mcp-0.2.0/src/pwpush_mcp/__init__.py +5 -0
  23. pwpush_mcp-0.2.0/src/pwpush_mcp/__main__.py +97 -0
  24. pwpush_mcp-0.2.0/src/pwpush_mcp/audit.py +110 -0
  25. pwpush_mcp-0.2.0/src/pwpush_mcp/client.py +448 -0
  26. pwpush_mcp-0.2.0/src/pwpush_mcp/config.py +143 -0
  27. pwpush_mcp-0.2.0/src/pwpush_mcp/durations.py +123 -0
  28. pwpush_mcp-0.2.0/src/pwpush_mcp/server.py +383 -0
  29. pwpush_mcp-0.2.0/tests/test_audit.py +100 -0
  30. pwpush_mcp-0.2.0/tests/test_catalog_metadata.py +66 -0
  31. pwpush_mcp-0.2.0/tests/test_client.py +183 -0
  32. pwpush_mcp-0.2.0/tests/test_config.py +96 -0
  33. pwpush_mcp-0.2.0/tests/test_durations.py +59 -0
  34. pwpush_mcp-0.2.0/tests/test_main.py +72 -0
  35. pwpush_mcp-0.2.0/tests/test_packaging.py +66 -0
  36. pwpush_mcp-0.2.0/tests/test_reliability.py +110 -0
  37. pwpush_mcp-0.2.0/tests/test_server.py +139 -0
@@ -0,0 +1,45 @@
1
+ # Password Pusher API token (generate at <base-url>/api_tokens).
2
+ # Whether it is required depends on the instance: some allow anonymous
3
+ # create/preview/expire. Listing and audit always require a token.
4
+ PWPUSH_API_TOKEN=
5
+
6
+ # Email tied to the API token. Required for authenticated calls on legacy
7
+ # (v1) instances, which use X-User-Email + X-User-Token headers.
8
+ PWPUSH_API_EMAIL=
9
+
10
+ # Base URL of the Password Pusher instance.
11
+ # Default: https://pwpush.com
12
+ # EU users: https://eu.pwpush.com
13
+ # Self-hosted: https://pwpush.example.com
14
+ PWPUSH_BASE_URL=https://pwpush.com
15
+
16
+ # API generation: auto (default), v1, or v2. 'auto' probes /api/v2/version
17
+ # and falls back to the legacy v1 endpoints when absent.
18
+ PWPUSH_API_VERSION=auto
19
+
20
+ # TLS verification. Set to false ONLY for internal instances with an untrusted
21
+ # certificate chain. Prefer PWPUSH_CA_BUNDLE with the instance's CA instead.
22
+ PWPUSH_VERIFY_SSL=true
23
+ # PWPUSH_CA_BUNDLE=/path/to/ca-bundle.pem
24
+
25
+ # --- Security / multi-tenant knobs ------------------------------------------
26
+ # Read-only mode: removes write tools (create_push, expire_push). Preview,
27
+ # list, audit and version remain available.
28
+ PWPUSH_READ_ONLY=false
29
+
30
+ # Tool allowlist (comma-separated fnmatch globs). Empty = all tools enabled.
31
+ # Example: list_*,get_version,preview_push
32
+ PWPUSH_ENABLED_TOOLS=
33
+
34
+ # Emit one JSON audit line per write-tool invocation on stderr.
35
+ PWPUSH_AUDIT_LOG=true
36
+
37
+ # --- Reliability knobs ------------------------------------------------------
38
+ # Cap concurrent in-flight HTTP requests. 0 = unlimited.
39
+ PWPUSH_MAX_CONCURRENT=0
40
+
41
+ # Retries for transient failures (connection errors, 429, 5xx) with backoff.
42
+ PWPUSH_MAX_RETRIES=2
43
+
44
+ # Per-request HTTP timeout, in seconds.
45
+ PWPUSH_TIMEOUT=30
@@ -0,0 +1,26 @@
1
+ version: 2
2
+ updates:
3
+ # Keep GitHub Actions SHA pins up to date automatically. Dependabot updates
4
+ # both the SHA and the inline version comment.
5
+ - package-ecosystem: github-actions
6
+ directory: /
7
+ schedule:
8
+ interval: weekly
9
+ day: monday
10
+ commit-message:
11
+ prefix: "chore(deps)"
12
+ labels:
13
+ - "ci/cd"
14
+ - "security"
15
+
16
+ # Keep Python dependencies up to date within the declared bounds. Upper bounds
17
+ # on mcp and httpx prevent silent breaking upgrades (see tests/test_packaging.py).
18
+ - package-ecosystem: pip
19
+ directory: /
20
+ schedule:
21
+ interval: weekly
22
+ day: monday
23
+ commit-message:
24
+ prefix: "chore(deps)"
25
+ labels:
26
+ - "ci/cd"
@@ -0,0 +1,43 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ci-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ lint-test:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ python: ["3.10", "3.11", "3.12", "3.13"]
19
+ steps:
20
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
21
+ - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
22
+ with:
23
+ python-version: ${{ matrix.python }}
24
+ cache: pip
25
+ - run: pip install -e ".[dev]"
26
+ - run: ruff check src tests
27
+ - run: ruff format --check src tests
28
+ - run: mypy src
29
+ - name: pytest with coverage
30
+ run: pytest -q --cov=pwpush_mcp --cov-report=term --cov-report=xml --cov-fail-under=80
31
+ - name: catalog metadata is up to date
32
+ run: |
33
+ python scripts/gen_metadata.py >/dev/null
34
+ git diff --exit-code catalog/metadata.json \
35
+ || { echo "catalog/metadata.json is stale — run scripts/gen_metadata.py and commit"; exit 1; }
36
+
37
+ docker:
38
+ needs: lint-test
39
+ runs-on: ubuntu-latest
40
+ steps:
41
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
42
+ - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
43
+ - run: docker build -t pwpush-mcp:ci .
@@ -0,0 +1,50 @@
1
+ name: Publish to PyPI (manual fallback)
2
+
3
+ # Automatic PyPI publishing on vX.Y.Z tags is handled by release.yml
4
+ # (publish-pypi job). This workflow exists only as a manual fallback via
5
+ # workflow_dispatch in case that job needs to be re-run independently.
6
+ on:
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+ id-token: write # required for PyPI trusted publishing
12
+
13
+ jobs:
14
+ build:
15
+ name: Build wheel + sdist
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
19
+ - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
20
+ with:
21
+ python-version: "3.12"
22
+ - run: pip install --upgrade build
23
+ - run: python -m build
24
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
25
+ with:
26
+ name: dist
27
+ path: dist/
28
+
29
+ publish:
30
+ name: Publish to PyPI (trusted publisher)
31
+ needs: build
32
+ runs-on: ubuntu-latest
33
+ environment:
34
+ name: pypi
35
+ url: https://pypi.org/p/pwpush-mcp
36
+ steps:
37
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
38
+ with:
39
+ name: dist
40
+ path: dist/
41
+ - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
42
+ with:
43
+ # OIDC trusted publishing — no token needed once the pending publisher
44
+ # is configured on pypi.org (Account Settings -> Publishing):
45
+ # PyPI project name: pwpush-mcp
46
+ # Repository owner: k9fr4n
47
+ # Repository name: pwpush-mcp
48
+ # Workflow name: pypi.yml
49
+ # Environment: pypi
50
+ attestations: true
@@ -0,0 +1,91 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: write # create GitHub Releases
10
+ packages: write # push to GHCR
11
+ id-token: write # PyPI OIDC trusted publishing
12
+
13
+ jobs:
14
+ image:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
18
+
19
+ - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
20
+ - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
21
+
22
+ - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
23
+ with:
24
+ registry: ghcr.io
25
+ username: ${{ github.actor }}
26
+ password: ${{ secrets.GITHUB_TOKEN }}
27
+
28
+ - id: meta
29
+ uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
30
+ with:
31
+ images: ghcr.io/${{ github.repository_owner }}/pwpush-mcp
32
+ tags: |
33
+ type=ref,event=branch
34
+ type=semver,pattern=v{{version}}
35
+ type=semver,pattern=v{{major}}.{{minor}}
36
+ type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
37
+
38
+ - name: Generate Docker MCP Gateway metadata label
39
+ run: |
40
+ pip install -e . -q
41
+ SERVER_METADATA=$(python scripts/gen_metadata.py)
42
+ echo "SERVER_METADATA=${SERVER_METADATA}" >> "$GITHUB_ENV"
43
+
44
+ - uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
45
+ with:
46
+ context: .
47
+ platforms: linux/amd64,linux/arm64
48
+ push: true
49
+ tags: ${{ steps.meta.outputs.tags }}
50
+ labels: ${{ steps.meta.outputs.labels }}
51
+ build-args: |
52
+ SERVER_METADATA=${{ env.SERVER_METADATA }}
53
+ provenance: true
54
+ sbom: true
55
+
56
+ # Create a GitHub Release only when a vX.Y.Z tag is pushed.
57
+ # --generate-notes builds the changelog from commits since the previous tag.
58
+ # `gh release create` is idempotent: it exits 0 if the release already exists.
59
+ - name: Create GitHub Release
60
+ if: startsWith(github.ref, 'refs/tags/v')
61
+ env:
62
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
63
+ run: |
64
+ gh release create "${GITHUB_REF_NAME}" \
65
+ --title "${GITHUB_REF_NAME}" \
66
+ --generate-notes \
67
+ --latest \
68
+ || echo "Release already exists, skipping."
69
+
70
+ # Publish to PyPI on every vX.Y.Z tag. Runs in the same workflow so the
71
+ # GITHUB_TOKEN cross-workflow event limitation is irrelevant.
72
+ publish-pypi:
73
+ name: Publish to PyPI
74
+ needs: image
75
+ runs-on: ubuntu-latest
76
+ if: startsWith(github.ref, 'refs/tags/v')
77
+ environment:
78
+ name: pypi
79
+ url: https://pypi.org/p/pwpush-mcp
80
+ permissions:
81
+ id-token: write # OIDC trusted publishing
82
+ steps:
83
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
84
+ - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
85
+ with:
86
+ python-version: "3.12"
87
+ - run: pip install --upgrade build
88
+ - run: python -m build
89
+ - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
90
+ with:
91
+ attestations: true
@@ -0,0 +1,31 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+
9
+ # Virtualenvs
10
+ .venv/
11
+ venv/
12
+ env/
13
+
14
+ # Tooling caches
15
+ .pytest_cache/
16
+ .ruff_cache/
17
+ .mypy_cache/
18
+ .coverage
19
+ coverage.xml
20
+ htmlcov/
21
+
22
+ # Local planning notes
23
+ .claude/plans/
24
+
25
+ # Env / secrets
26
+ .env
27
+ .env.local
28
+ .mcp.json
29
+
30
+ # OS
31
+ .DS_Store
@@ -0,0 +1,26 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-json
9
+ - id: check-added-large-files
10
+ - id: check-merge-conflict
11
+
12
+ - repo: https://github.com/astral-sh/ruff-pre-commit
13
+ rev: v0.8.0
14
+ hooks:
15
+ - id: ruff
16
+ args: [--fix]
17
+ - id: ruff-format
18
+
19
+ - repo: https://github.com/pre-commit/mirrors-mypy
20
+ rev: v1.13.0
21
+ hooks:
22
+ - id: mypy
23
+ files: ^src/
24
+ additional_dependencies:
25
+ - httpx>=0.27
26
+ - mcp[cli]>=1.2.0
@@ -0,0 +1,55 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.2.0] - 2026-06-05
10
+
11
+ First packaged, distributable release. The server moves to the low-level MCP
12
+ SDK, gains an HTTP transport, security/multi-tenant knobs, and a full
13
+ distribution + governance setup inspired by
14
+ [thruk-mcp](https://github.com/k9fr4n/thruk-mcp).
15
+
16
+ ### Added
17
+
18
+ - **HTTP transport**: `pwpush-mcp --listen PORT` exposes the server over
19
+ Streamable-HTTP/SSE (Starlette + uvicorn). `--host` / `--log-level` flags.
20
+ stdio remains the default.
21
+ - **Docker image**: multi-stage `Dockerfile` (non-root user, wheel build) and
22
+ `compose.yml`. Published to `ghcr.io/k9fr4n/pwpush-mcp` on each `vX.Y.Z` tag.
23
+ - **Docker MCP Gateway**: `catalog/server.yaml` + generated `catalog/metadata.json`
24
+ and the `io.docker.server.metadata` OCI label so the gateway forwards tool
25
+ arguments correctly. `scripts/gen_metadata.py` regenerates the catalog.
26
+ - **Release automation**: `release.yml` builds multi-arch (amd64/arm64) images
27
+ with SBOM + provenance, creates the GitHub Release, and publishes to PyPI via
28
+ OIDC trusted publishing. `pypi.yml` is a manual fallback. `dependabot.yml`
29
+ keeps Actions (SHA-pinned) and Python deps current.
30
+ - **Security / multi-tenant knobs**:
31
+ - `PWPUSH_READ_ONLY=true` removes write tools (`create_push`, `expire_push`).
32
+ - `PWPUSH_ENABLED_TOOLS=list_*,get_version` restricts the exposed tool surface
33
+ via fnmatch globs.
34
+ - `PWPUSH_AUDIT_LOG=true` (default) emits one JSON line per write-tool
35
+ invocation on the `pwpush_mcp.audit` logger; secrets are redacted.
36
+ - **Reliability knobs**: `PWPUSH_MAX_CONCURRENT` (concurrency cap),
37
+ `PWPUSH_MAX_RETRIES` (transport retries + 429/5xx backoff honouring
38
+ `Retry-After`), `PWPUSH_TIMEOUT`.
39
+ - **Governance**: `CONTRIBUTING.md`, `SUPPORT.md`, `UPGRADING.md`,
40
+ `.pre-commit-config.yaml`, this `CHANGELOG.md`.
41
+ - New tests for config knobs, tool filtering, audit logging, retries/concurrency,
42
+ catalog drift, and dependency bounds.
43
+
44
+ ### Changed
45
+
46
+ - **Server rewritten on the low-level MCP SDK** (`mcp.server.Server`) instead of
47
+ FastMCP, with explicit `inputSchema` per tool. Dependency `fastmcp` replaced by
48
+ `mcp[cli]` (+ `uvicorn`, `starlette`).
49
+ - `Config.__repr__` / `__str__` now redact the API token unconditionally.
50
+ - CI gained `ruff format --check`, `mypy src`, a 80% coverage gate, a catalog
51
+ drift check, and a Docker build job; Actions are pinned to commit SHAs.
52
+ - Dependency upper bounds added for `mcp` (`<2.0`) and `httpx` (`<1.0`).
53
+
54
+ [Unreleased]: https://github.com/k9fr4n/pwpush-mcp/compare/v0.2.0...HEAD
55
+ [0.2.0]: https://github.com/k9fr4n/pwpush-mcp/releases/tag/v0.2.0
@@ -0,0 +1,65 @@
1
+ # Contributing to pwpush-mcp
2
+
3
+ Thanks for your interest! This is a small, focused MCP server — contributions
4
+ that keep it simple and secure are very welcome.
5
+
6
+ ## Development setup
7
+
8
+ ```bash
9
+ python -m venv .venv && source .venv/bin/activate
10
+ pip install -e ".[dev]"
11
+ pre-commit install # optional but recommended
12
+ ```
13
+
14
+ ## Before opening a PR
15
+
16
+ Run the same checks CI runs:
17
+
18
+ ```bash
19
+ ruff check src tests
20
+ ruff format --check src tests
21
+ mypy src
22
+ pytest -q --cov=pwpush_mcp --cov-fail-under=80
23
+ python scripts/gen_metadata.py >/dev/null # if you touched the tool surface
24
+ ```
25
+
26
+ `pre-commit run --all-files` runs the lint/format/type subset automatically.
27
+
28
+ ## Design invariants (please preserve)
29
+
30
+ - **Never retrieve a push payload.** Retrieving consumes a view irreversibly; it
31
+ must stay a human action via the secret URL. There is intentionally no
32
+ `retrieve` tool.
33
+ - **The API token is never a tool argument.** It comes only from
34
+ `PWPUSH_API_TOKEN` so the model can neither supply nor log it.
35
+ - **Secrets never reach logs.** `payload` / `passphrase` / file contents are
36
+ stripped from returned objects (`client._public`) and from audit lines
37
+ (`audit._redact` / `audit.scrub`). `Config.__repr__` redacts the token.
38
+
39
+ ## Adding a tool
40
+
41
+ 1. Add an async handler and a `ToolSpec` to `TOOL_REGISTRY` in
42
+ `src/pwpush_mcp/server.py` (set `is_write` / `destructive` correctly).
43
+ 2. Regenerate the catalog: `python scripts/gen_metadata.py >/dev/null` and commit
44
+ `catalog/metadata.json` (CI fails on drift).
45
+ 3. Add tests under `tests/`.
46
+
47
+ ## Adding an env var
48
+
49
+ 1. Add the field + parsing in `src/pwpush_mcp/config.py`.
50
+ 2. Document it in `.env.example` and the README configuration table.
51
+ 3. If it is operator-facing, add it to `catalog/server.yaml`.
52
+
53
+ ## Commit / PR conventions
54
+
55
+ - Conventional-commit style prefixes (`feat:`, `fix:`, `chore:`, `docs:`, `ci:`).
56
+ - One logical change per PR; update `CHANGELOG.md` under `[Unreleased]`.
57
+
58
+ ## Releasing (maintainers)
59
+
60
+ 1. Move `[Unreleased]` notes to a new `[X.Y.Z]` section in `CHANGELOG.md`.
61
+ 2. Bump `version` in `pyproject.toml` and `__version__` in
62
+ `src/pwpush_mcp/__init__.py`.
63
+ 3. Tag and push: `git tag vX.Y.Z && git push origin vX.Y.Z`.
64
+ 4. `release.yml` builds/pushes the multi-arch image, creates the GitHub Release,
65
+ and publishes to PyPI (OIDC). No manual token handling.
@@ -0,0 +1,30 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ FROM python:3.12-slim AS build
3
+ WORKDIR /src
4
+ RUN pip install --no-cache-dir build
5
+ COPY pyproject.toml README.md ./
6
+ COPY src ./src
7
+ RUN python -m build --wheel --outdir /dist
8
+
9
+ FROM python:3.12-slim
10
+ RUN useradd -r -u 1001 -m pwpush
11
+ WORKDIR /app
12
+ COPY --from=build /dist/*.whl /tmp/
13
+ RUN pip install --no-cache-dir /tmp/*.whl && rm -f /tmp/*.whl
14
+
15
+ # Embed the Docker MCP Gateway catalog metadata so that self-configured
16
+ # deployments (docker:// references) expose correct tool argument schemas.
17
+ # Without this label the gateway uses empty schemas and strips all arguments
18
+ # before forwarding tool calls, causing "Field required" errors at runtime.
19
+ # The value is produced by scripts/gen_metadata.py and injected at build time:
20
+ # --build-arg SERVER_METADATA="$(python scripts/gen_metadata.py)"
21
+ ARG SERVER_METADATA="{}"
22
+ LABEL io.docker.server.metadata="$SERVER_METADATA"
23
+
24
+ USER pwpush
25
+ ENV PYTHONUNBUFFERED=1
26
+ # Default = stdio transport (Docker MCP Gateway / Claude Desktop / Claude Code).
27
+ # For HTTP/Streamable-HTTP, override CMD: ["--listen", "8000"]
28
+ EXPOSE 8000
29
+ ENTRYPOINT ["pwpush-mcp"]
30
+ CMD []
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 pwpush-mcp contributors
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.