mcp-behaviour-guard 0.4.1__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 (91) hide show
  1. mcp_behaviour_guard-0.4.1/.env.example +13 -0
  2. mcp_behaviour_guard-0.4.1/.github/workflows/ci.yml +80 -0
  3. mcp_behaviour_guard-0.4.1/.gitignore +27 -0
  4. mcp_behaviour_guard-0.4.1/CHANGELOG.md +50 -0
  5. mcp_behaviour_guard-0.4.1/CONTRIBUTING.md +32 -0
  6. mcp_behaviour_guard-0.4.1/Dockerfile +18 -0
  7. mcp_behaviour_guard-0.4.1/Dockerfile.runner +35 -0
  8. mcp_behaviour_guard-0.4.1/LICENSE +21 -0
  9. mcp_behaviour_guard-0.4.1/Makefile +35 -0
  10. mcp_behaviour_guard-0.4.1/PKG-INFO +568 -0
  11. mcp_behaviour_guard-0.4.1/README.md +532 -0
  12. mcp_behaviour_guard-0.4.1/SECURITY.md +9 -0
  13. mcp_behaviour_guard-0.4.1/contracts/http-demo.yaml +181 -0
  14. mcp_behaviour_guard-0.4.1/contracts/stdio-demo.yaml +159 -0
  15. mcp_behaviour_guard-0.4.1/contracts/temporal-demo.yaml +72 -0
  16. mcp_behaviour_guard-0.4.1/demo/server/__init__.py +1 -0
  17. mcp_behaviour_guard-0.4.1/demo/server/app.py +300 -0
  18. mcp_behaviour_guard-0.4.1/demo/stdio_server/__init__.py +1 -0
  19. mcp_behaviour_guard-0.4.1/demo/stdio_server/app.py +105 -0
  20. mcp_behaviour_guard-0.4.1/demo/telemetry/__init__.py +1 -0
  21. mcp_behaviour_guard-0.4.1/demo/telemetry/app.py +44 -0
  22. mcp_behaviour_guard-0.4.1/demo/temporal_server/__init__.py +0 -0
  23. mcp_behaviour_guard-0.4.1/demo/temporal_server/app.py +115 -0
  24. mcp_behaviour_guard-0.4.1/demo/watcher/__init__.py +1 -0
  25. mcp_behaviour_guard-0.4.1/demo/watcher/app.py +73 -0
  26. mcp_behaviour_guard-0.4.1/demo_runtime/.gitkeep +0 -0
  27. mcp_behaviour_guard-0.4.1/docker-compose.yml +57 -0
  28. mcp_behaviour_guard-0.4.1/docs/architecture.md +93 -0
  29. mcp_behaviour_guard-0.4.1/docs/comparison-sources.md +50 -0
  30. mcp_behaviour_guard-0.4.1/docs/contract-reference.md +214 -0
  31. mcp_behaviour_guard-0.4.1/docs/demo-results.md +116 -0
  32. mcp_behaviour_guard-0.4.1/docs/evidence-status.md +24 -0
  33. mcp_behaviour_guard-0.4.1/docs/images/config-provenance-drift.png +0 -0
  34. mcp_behaviour_guard-0.4.1/docs/images/http-report.png +0 -0
  35. mcp_behaviour_guard-0.4.1/docs/images/http-shell.png +0 -0
  36. mcp_behaviour_guard-0.4.1/docs/images/mcp-behaviour-guard-overview.png +0 -0
  37. mcp_behaviour_guard-0.4.1/docs/images/stdio-report.png +0 -0
  38. mcp_behaviour_guard-0.4.1/docs/images/stdio-shell.png +0 -0
  39. mcp_behaviour_guard-0.4.1/docs/images/temporal-report.png +0 -0
  40. mcp_behaviour_guard-0.4.1/docs/images/temporal-shell.png +0 -0
  41. mcp_behaviour_guard-0.4.1/docs/local-agent-demo.md +22 -0
  42. mcp_behaviour_guard-0.4.1/docs/sample-stdio-report.html +923 -0
  43. mcp_behaviour_guard-0.4.1/docs/temporal-integrity.md +34 -0
  44. mcp_behaviour_guard-0.4.1/docs/threat-model.md +74 -0
  45. mcp_behaviour_guard-0.4.1/examples/clients/vscode-mcp.json +27 -0
  46. mcp_behaviour_guard-0.4.1/examples/role-policy.yaml +17 -0
  47. mcp_behaviour_guard-0.4.1/examples/scheduling/com.example.mcp-behaviour-guard.plist +22 -0
  48. mcp_behaviour_guard-0.4.1/examples/scheduling/cron.example +4 -0
  49. mcp_behaviour_guard-0.4.1/examples/tenants.csv +6 -0
  50. mcp_behaviour_guard-0.4.1/pyproject.toml +75 -0
  51. mcp_behaviour_guard-0.4.1/scripts/run-http-demo.sh +6 -0
  52. mcp_behaviour_guard-0.4.1/scripts/run-stdio-demo.sh +6 -0
  53. mcp_behaviour_guard-0.4.1/scripts/run-temporal-demo.sh +5 -0
  54. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/__init__.py +23 -0
  55. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/alerts.py +82 -0
  56. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/baseline.py +126 -0
  57. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/cli.py +420 -0
  58. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/client.py +371 -0
  59. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/config.py +81 -0
  60. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/contract_tools.py +282 -0
  61. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/engine.py +1171 -0
  62. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/evidence.py +67 -0
  63. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/host_config.py +376 -0
  64. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/models.py +441 -0
  65. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/observers/__init__.py +25 -0
  66. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/observers/base.py +24 -0
  67. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/observers/filesystem.py +62 -0
  68. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/observers/http_audit.py +47 -0
  69. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/observers/jsonl_audit.py +51 -0
  70. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/reporting.py +157 -0
  71. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/runner.py +39 -0
  72. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/storage.py +213 -0
  73. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/templates/report.html +137 -0
  74. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/temporal.py +94 -0
  75. mcp_behaviour_guard-0.4.1/src/mcp_behaviour_guard/util.py +52 -0
  76. mcp_behaviour_guard-0.4.1/tests/test_alerts.py +55 -0
  77. mcp_behaviour_guard-0.4.1/tests/test_baseline.py +27 -0
  78. mcp_behaviour_guard-0.4.1/tests/test_client_metadata.py +70 -0
  79. mcp_behaviour_guard-0.4.1/tests/test_config.py +49 -0
  80. mcp_behaviour_guard-0.4.1/tests/test_contract_tools.py +57 -0
  81. mcp_behaviour_guard-0.4.1/tests/test_engine_rules.py +43 -0
  82. mcp_behaviour_guard-0.4.1/tests/test_evidence_semantics.py +560 -0
  83. mcp_behaviour_guard-0.4.1/tests/test_filesystem_observer.py +21 -0
  84. mcp_behaviour_guard-0.4.1/tests/test_host_config.py +264 -0
  85. mcp_behaviour_guard-0.4.1/tests/test_reporting.py +51 -0
  86. mcp_behaviour_guard-0.4.1/tests/test_safety_gate.py +43 -0
  87. mcp_behaviour_guard-0.4.1/tests/test_stdio_client.py +33 -0
  88. mcp_behaviour_guard-0.4.1/tests/test_storage.py +53 -0
  89. mcp_behaviour_guard-0.4.1/tests/test_temporal.py +81 -0
  90. mcp_behaviour_guard-0.4.1/tests/test_temporal_contract.py +95 -0
  91. mcp_behaviour_guard-0.4.1/tests/test_temporal_engine.py +98 -0
@@ -0,0 +1,13 @@
1
+ TENANT_A_TOKEN=tenant-a-token
2
+ TENANT_B_TOKEN=tenant-b-token
3
+ READ_ONLY_TOKEN=readonly-token
4
+ ADMIN_TOKEN=admin-token
5
+
6
+ TENANT_A_READER_TOKEN=replace-me
7
+ TENANT_A_OPERATOR_TOKEN=replace-me
8
+ TENANT_B_READER_TOKEN=replace-me
9
+ TENANT_B_OPERATOR_TOKEN=replace-me
10
+ TENANT_C_READER_TOKEN=replace-me
11
+
12
+ DEMO_AGENT_TOKEN=local-demo-token
13
+ MCP_GUARD_WEBHOOK=
@@ -0,0 +1,80 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: '3.11.14'
18
+ cache: pip
19
+ - run: python -m pip install --upgrade pip
20
+ - run: python -m pip install -e '.[dev]'
21
+ - run: ruff format --check .
22
+ - run: ruff check .
23
+ - run: mypy src/mcp_behaviour_guard
24
+ - run: pytest
25
+
26
+ integration-demos:
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: '3.11.14'
33
+ cache: pip
34
+ - run: python -m pip install --upgrade pip
35
+ - run: python -m pip install -e .
36
+ - name: Run STDIO security contract
37
+ env:
38
+ DEMO_AGENT_TOKEN: ci-fake-secret
39
+ run: mcp-guard run contracts/stdio-demo.yaml --lab-mode --no-fail --output reports-stdio --database .guard/stdio.db
40
+ - name: Run temporal metadata-drift demo
41
+ run: mcp-guard run contracts/temporal-demo.yaml --no-fail --output reports-temporal --database .guard/temporal.db
42
+ - name: Verify temporal drift was detected after repeated calls
43
+ run: |
44
+ python - <<'PY'
45
+ import json
46
+ from pathlib import Path
47
+
48
+ reports = list(Path("reports-temporal").glob("*/report.json"))
49
+ assert len(reports) == 1, f"expected one temporal report, got {len(reports)}"
50
+ payload = json.loads(reports[0].read_text(encoding="utf-8"))
51
+ finding = next(
52
+ item for item in payload["findings"]
53
+ if item["test_id"] == "TEMPORAL-METADATA-001"
54
+ )
55
+ assert finding["status"] == "failed", finding
56
+ assert finding["severity"] == "high", finding
57
+ assert finding["observed"]["first_drift"]["after_call"] == 3, finding
58
+ PY
59
+ - name: Start HTTP lab
60
+ run: docker compose up --build -d --wait
61
+ - name: Run HTTP security contract
62
+ run: mcp-guard run contracts/http-demo.yaml --lab-mode --no-fail --output reports-http --database .guard/http.db
63
+ - name: Verify reports exist
64
+ run: |
65
+ test -n "$(find reports-stdio -name index.html -print -quit)"
66
+ test -n "$(find reports-temporal -name index.html -print -quit)"
67
+ test -n "$(find reports-http -name index.html -print -quit)"
68
+ - if: always()
69
+ run: docker compose down -v
70
+
71
+ docker-build:
72
+ runs-on: ubuntu-latest
73
+ steps:
74
+ - uses: actions/checkout@v4
75
+ - uses: docker/setup-buildx-action@v3
76
+ - uses: docker/build-push-action@v6
77
+ with:
78
+ context: .
79
+ push: false
80
+ platforms: linux/amd64,linux/arm64
@@ -0,0 +1,27 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ .pytest_cache/
5
+ .mypy_cache/
6
+ .ruff_cache/
7
+ .coverage
8
+ htmlcov/
9
+ .DS_Store
10
+ .env
11
+ .guard/
12
+ reports/
13
+ baselines/
14
+ baseline-diff.json
15
+ demo_runtime/*
16
+ !demo_runtime/.gitkeep
17
+ dist/
18
+ build/
19
+ *.egg-info/
20
+ *.db
21
+ host-config-diff.json
22
+
23
+ # Local validation evidence generated during demo/regression runs
24
+ reports-temporal/
25
+ reports-regression-http/
26
+ reports-regression-stdio/
27
+ reports-*/
@@ -0,0 +1,50 @@
1
+ # Changelog
2
+
3
+ ## 0.4.1 - 2026-09-17
4
+ - Fix the duplicated Safety and limitations heading in the README.
5
+ - Add package-index project links for the repository, issue tracker and changelog.
6
+ - Modernize MIT license metadata to the SPDX/PEP 639 format.
7
+ - Prepare package metadata for the initial PyPI publication.
8
+
9
+ ## 0.4.0 - 2026-09-16
10
+ - Distinguish confirmed denials from failed connections and generic tool errors.
11
+ - Require a working positive control before a negative authorization check passes.
12
+ - Report observer outages and zero-effect replay runs as inconclusive.
13
+ - Do not start replay or state-changing behaviour probes when required observers fail to start.
14
+ - Omit raw invocation arguments and responses from exported traces and reports.
15
+ - Expose the contract runner to Python callers and add a separate CLI runner image.
16
+ - Keep MCP SDK v2 migration and PyPI publishing out of this patch.
17
+
18
+ ## 0.3.0
19
+
20
+ - Removed the optional suggestion command and its external suggestion-service probe from the CLI.
21
+ - Added persistent-session temporal-integrity checks with configurable re-tests per session.
22
+ - Temporal drivers are contract-validated as reviewed read-only tools before execution.
23
+ - Added deterministic fingerprints and before/after evidence for tool, prompt and resource metadata.
24
+ - Added prompt payload probes and capture of MCP list-change notifications.
25
+ - Added a harmless three-call sleeper demo that changes metadata without touching credentials or external services.
26
+ - Added redacted MCP host-configuration snapshot/diff commands for supply-chain provenance checks, including additional server controls and VS Code-style sandbox/input blocks.
27
+ - Added JSONC/JSON5-style parsing for common editor MCP configuration files.
28
+ - Added CI coverage that verifies the temporal demo detects drift after the third call.
29
+ - Kept the MCP Python SDK pinned at `1.28.1`; SDK 2.x / protocol 2026-07-28 subscription handling is intentionally left for a separately validated migration.
30
+
31
+
32
+ ## 0.2.0
33
+
34
+ - Added first-class STDIO transport support.
35
+ - Added a deliberately vulnerable local-agent MCP demonstration.
36
+ - Added conservative contract draft generation from MCP discovery.
37
+ - Added CSV and role-policy tenant compilation with per-tenant allow/deny exceptions.
38
+ - Added deterministic path-boundary and inherited-secret response probes.
39
+ - Added JSONL side-effect observation for controlled STDIO labs.
40
+ - Added interval monitoring, high/critical webhook alerts and SQLite deduplication.
41
+ - Improved HTML reports with critical-first rows, filtering and expandable evidence.
42
+ - Added MCP configuration examples for local and editor-based clients.
43
+ - Added macOS launchd and Ubuntu cron scheduling templates.
44
+ - Added HTTP and STDIO integration checks to CI.
45
+
46
+ ## 0.1.0
47
+
48
+ - Initial Streamable HTTP security-contract harness.
49
+ - Authorization, tenant isolation, session isolation, side-effect, replay and baseline checks.
50
+ - SQLite, HTML, JSON, JUnit and SARIF reporting.
@@ -0,0 +1,32 @@
1
+ # Contributing
2
+
3
+ ## Local checks
4
+
5
+ ```bash
6
+ python -m pip install -e '.[dev]'
7
+ ruff format .
8
+ ruff check .
9
+ mypy src/mcp_behaviour_guard
10
+ pytest
11
+ ```
12
+
13
+ Exercise the demonstrations when changing clients, observers or engine behaviour:
14
+
15
+ ```bash
16
+ make demo-stdio
17
+ docker compose up --build -d
18
+ make demo-http
19
+ docker compose down -v
20
+ ```
21
+
22
+ Keep pass/fail rules deterministic. Changes to security checks must remain reviewable and require normal code review.
23
+
24
+ New checks should include:
25
+
26
+ - a contract field or explicit test input;
27
+ - an objective expected property;
28
+ - reproducible observed evidence;
29
+ - a unit test for pass and fail cases; and
30
+ - a safety note when the check can change state.
31
+
32
+ Do not submit real credentials, customer data or scan evidence from systems you are not authorized to test.
@@ -0,0 +1,18 @@
1
+ FROM python:3.11.14-slim
2
+
3
+ ENV PYTHONDONTWRITEBYTECODE=1 \
4
+ PYTHONUNBUFFERED=1 \
5
+ PIP_NO_CACHE_DIR=1
6
+
7
+ WORKDIR /app
8
+ COPY pyproject.toml README.md LICENSE ./
9
+ COPY src ./src
10
+ COPY demo ./demo
11
+ RUN python -m pip install --upgrade pip && python -m pip install .
12
+
13
+ RUN useradd --create-home --uid 10001 guard && \
14
+ mkdir -p /data /runtime && \
15
+ chown -R guard:guard /app /data /runtime
16
+ USER guard
17
+
18
+ CMD ["uvicorn", "demo.server.app:app", "--host", "0.0.0.0", "--port", "8000"]
@@ -0,0 +1,35 @@
1
+ FROM python:3.11.14-slim
2
+
3
+ ENV PYTHONDONTWRITEBYTECODE=1 \
4
+ PYTHONUNBUFFERED=1 \
5
+ PIP_NO_CACHE_DIR=1
6
+
7
+ WORKDIR /app
8
+ COPY pyproject.toml README.md LICENSE ./
9
+ COPY src ./src
10
+ RUN printf '%s\n' \
11
+ 'Types: deb' \
12
+ 'URIs: https://deb.debian.org/debian' \
13
+ 'Suites: trixie trixie-updates' \
14
+ 'Components: main' \
15
+ 'Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg' \
16
+ '' \
17
+ 'Types: deb' \
18
+ 'URIs: https://security.debian.org/debian-security' \
19
+ 'Suites: trixie-security' \
20
+ 'Components: main' \
21
+ 'Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg' \
22
+ > /etc/apt/sources.list.d/debian.sources && \
23
+ apt-get -o Acquire::Retries=5 update && \
24
+ DEBIAN_FRONTEND=noninteractive apt-get -y upgrade && \
25
+ rm -rf /var/lib/apt/lists/* && \
26
+ python -m pip install . && \
27
+ python -m pip uninstall -y wheel setuptools && \
28
+ useradd --create-home --uid 10001 guard && \
29
+ mkdir -p /work && \
30
+ chown guard:guard /work
31
+
32
+ USER guard
33
+ WORKDIR /work
34
+ ENTRYPOINT ["mcp-guard"]
35
+ CMD ["--help"]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arjun Arjun
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,35 @@
1
+ .PHONY: install lint format test demo-up demo-down demo-http demo-stdio demo-temporal clean
2
+
3
+ install:
4
+ python -m pip install -e '.[dev]'
5
+
6
+ lint:
7
+ ruff format --check .
8
+ ruff check .
9
+ mypy src/mcp_behaviour_guard
10
+
11
+ format:
12
+ ruff format .
13
+ ruff check --fix .
14
+
15
+ test:
16
+ pytest
17
+
18
+ demo-up:
19
+ docker compose up --build -d
20
+
21
+ demo-down:
22
+ docker compose down -v
23
+
24
+ demo-http:
25
+ mcp-guard run contracts/http-demo.yaml --lab-mode --no-fail
26
+
27
+ demo-stdio:
28
+ DEMO_AGENT_TOKEN=local-demo-token mcp-guard run contracts/stdio-demo.yaml --lab-mode --no-fail
29
+
30
+ demo-temporal:
31
+ mcp-guard run contracts/temporal-demo.yaml --no-fail
32
+
33
+ clean:
34
+ rm -rf .guard reports reports-http reports-stdio reports-temporal baselines baseline-diff.json host-config-diff.json
35
+ find demo_runtime -type f ! -name .gitkeep -delete