redacted-context-mcp 0.7.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 (41) hide show
  1. redacted_context_mcp-0.7.0/.github/workflows/test.yml +64 -0
  2. redacted_context_mcp-0.7.0/.gitignore +15 -0
  3. redacted_context_mcp-0.7.0/ARCHITECTURE.md +134 -0
  4. redacted_context_mcp-0.7.0/CHANGELOG.md +112 -0
  5. redacted_context_mcp-0.7.0/CONTRIBUTING.md +56 -0
  6. redacted_context_mcp-0.7.0/LICENSE +21 -0
  7. redacted_context_mcp-0.7.0/PKG-INFO +550 -0
  8. redacted_context_mcp-0.7.0/README.md +521 -0
  9. redacted_context_mcp-0.7.0/SECURITY.md +25 -0
  10. redacted_context_mcp-0.7.0/SECURITY_INVARIANTS.md +109 -0
  11. redacted_context_mcp-0.7.0/SETUP.md +204 -0
  12. redacted_context_mcp-0.7.0/examples/agent-AGENTS.md +25 -0
  13. redacted_context_mcp-0.7.0/examples/agent-CLAUDE.md +31 -0
  14. redacted_context_mcp-0.7.0/examples/claude-settings.example.json +22 -0
  15. redacted_context_mcp-0.7.0/examples/codex-config.example.toml +5 -0
  16. redacted_context_mcp-0.7.0/examples/mcp.installed.json +12 -0
  17. redacted_context_mcp-0.7.0/examples/mcp.source.json +13 -0
  18. redacted_context_mcp-0.7.0/examples/redaction-config.toml +6 -0
  19. redacted_context_mcp-0.7.0/pyproject.toml +74 -0
  20. redacted_context_mcp-0.7.0/src/redacted_context_mcp/__init__.py +23 -0
  21. redacted_context_mcp-0.7.0/src/redacted_context_mcp/config.py +347 -0
  22. redacted_context_mcp-0.7.0/src/redacted_context_mcp/core.py +1660 -0
  23. redacted_context_mcp-0.7.0/src/redacted_context_mcp/defaults.py +627 -0
  24. redacted_context_mcp-0.7.0/src/redacted_context_mcp/discovery.py +748 -0
  25. redacted_context_mcp-0.7.0/src/redacted_context_mcp/filesystem.py +474 -0
  26. redacted_context_mcp-0.7.0/src/redacted_context_mcp/github.py +306 -0
  27. redacted_context_mcp-0.7.0/src/redacted_context_mcp/limits.py +82 -0
  28. redacted_context_mcp-0.7.0/src/redacted_context_mcp/models.py +75 -0
  29. redacted_context_mcp-0.7.0/src/redacted_context_mcp/paths.py +36 -0
  30. redacted_context_mcp-0.7.0/src/redacted_context_mcp/redaction.py +371 -0
  31. redacted_context_mcp-0.7.0/src/redacted_context_mcp/server.py +1442 -0
  32. redacted_context_mcp-0.7.0/tests/__init__.py +1 -0
  33. redacted_context_mcp-0.7.0/tests/fixtures.py +65 -0
  34. redacted_context_mcp-0.7.0/tests/test_cli.py +190 -0
  35. redacted_context_mcp-0.7.0/tests/test_discovery.py +471 -0
  36. redacted_context_mcp-0.7.0/tests/test_followup_hardening.py +592 -0
  37. redacted_context_mcp-0.7.0/tests/test_github.py +162 -0
  38. redacted_context_mcp-0.7.0/tests/test_mcp.py +531 -0
  39. redacted_context_mcp-0.7.0/tests/test_redaction.py +76 -0
  40. redacted_context_mcp-0.7.0/tests/test_security_hardening.py +331 -0
  41. redacted_context_mcp-0.7.0/tests/test_v070_security_hardening.py +697 -0
@@ -0,0 +1,64 @@
1
+ name: test
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ${{ matrix.os }}
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ os:
19
+ - ubuntu-latest
20
+ - windows-latest
21
+ - macos-latest
22
+ python-version:
23
+ - "3.11"
24
+ - "3.12"
25
+ - "3.13"
26
+ steps:
27
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
28
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+ - run: python -m pip install --upgrade pip
32
+ - run: python -m pip install -e .
33
+ - run: python -m unittest discover -s tests -p 'test_*.py'
34
+ - run: python -m py_compile src/redacted_context_mcp/core.py src/redacted_context_mcp/server.py
35
+
36
+ package:
37
+ runs-on: ubuntu-latest
38
+ steps:
39
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
40
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
41
+ with:
42
+ python-version: "3.13"
43
+ - run: python -m pip install --upgrade pip
44
+ - run: python -m pip install build twine
45
+ - run: python -m build
46
+ - run: python -m twine check dist/*
47
+ - name: Smoke test built wheel
48
+ shell: python
49
+ run: |
50
+ import glob
51
+ import os
52
+ import subprocess
53
+ import sys
54
+
55
+ wheels = glob.glob("dist/*.whl")
56
+ if len(wheels) != 1:
57
+ raise SystemExit(f"Expected one wheel, found {wheels!r}")
58
+ subprocess.check_call([sys.executable, "-m", "venv", "wheel-smoke"])
59
+ python = os.path.join("wheel-smoke", "bin", "python")
60
+ subprocess.check_call([python, "-m", "pip", "install", "--upgrade", "pip"])
61
+ subprocess.check_call([python, "-m", "pip", "install", wheels[0]])
62
+ bin_dir = os.path.join("wheel-smoke", "bin")
63
+ subprocess.check_call([os.path.join(bin_dir, "redctx"), "--help"])
64
+ subprocess.check_call([os.path.join(bin_dir, "redctx-mcp"), "--help"])
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ .pytest_cache/
3
+ .ruff_cache/
4
+ .mypy_cache/
5
+ .venv/
6
+ venv/
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ .DS_Store
11
+ .chloe/
12
+ .agent-context-redactor.toml
13
+ .redacted-context-mcp/
14
+ agent-workdir/work/*
15
+ !agent-workdir/work/.gitkeep
@@ -0,0 +1,134 @@
1
+ # Architecture
2
+
3
+ `redacted-context-mcp` exposes a private local knowledgebase through a narrow
4
+ redaction layer. The default MCP surface is read-only; controlled writes are
5
+ available only when the server is started with explicit write flags. The project
6
+ is intentionally small: it avoids runtime dependencies, stores no persistent
7
+ index, and keeps all sensitive configuration local.
8
+
9
+ ## Data Flow
10
+
11
+ ```text
12
+ agent workspace
13
+ -> MCP client or redctx CLI
14
+ -> redaction layer
15
+ -> private source root
16
+ -> redacted text plus opaque path references
17
+ ```
18
+
19
+ The agent should start from a neutral workspace that does not contain the raw
20
+ private context files. The MCP server receives tool calls, resolves paths inside
21
+ the configured root, reads allowed text files, redacts output, and returns only
22
+ the redacted result. If controlled writes are enabled, generated redacted text
23
+ can be rehydrated locally and written under a configured private-root
24
+ subdirectory.
25
+
26
+ ## Core Boundaries
27
+
28
+ - The server is read-only by default.
29
+ - Controlled MCP writes require `--enable-writes` and are constrained to
30
+ `--write-subdir`.
31
+ - Path resolution is constrained to the configured root.
32
+ - Known private/cache paths and binary-like files are excluded by default.
33
+ - File navigation uses local-salted HMAC ids such as `@p_1a2b3c4d5e6f`.
34
+ - Filesystem traversal starts from validated paths, skips symlink and reparse
35
+ entries, and revalidates paths before content reads and opaque-id resolution.
36
+ - Content reads compare file metadata before and after reading to detect common
37
+ substitutions, but the project remains a guardrail rather than a hard
38
+ concurrent-mutation sandbox.
39
+ - Redacted files are available as MCP resources with `redctx://p_<id>` URIs.
40
+ - MCP resource content is cached only after redaction and is bounded by byte
41
+ limits.
42
+ - The stdio server supports both stateless MCP `2026-07-28` requests and the
43
+ legacy initialization-based protocol through `2025-11-25`.
44
+ - Opaque path references are explicit request arguments rather than implicit
45
+ protocol-session state. In-memory path and content indexes are reconstructable
46
+ caches; the persistent vault salt is durable server configuration.
47
+ - Redaction happens before file content, file paths, search results, bundles,
48
+ and GitHub issue text are returned.
49
+
50
+ ## Module Layout
51
+
52
+ - `core.py`: CLI commands, parser setup, and compatibility re-exports.
53
+ - `server.py`: minimal stdio MCP JSON-RPC server.
54
+ - `defaults.py`: default limits, allow lists, exclude lists, and compiled
55
+ patterns.
56
+ - `models.py`: shared dataclasses.
57
+ - `redaction.py`: text/path redaction logic.
58
+ - `config.py`: local TOML config loading and validation.
59
+ - `paths.py`: root-constrained path resolution and opaque path ids.
60
+ - `filesystem.py`: read-only filesystem traversal and text-file detection.
61
+ - `discovery.py`: local Ollama discovery workflow and post-processing.
62
+ - `github.py`: read-only GitHub issue access through neutral aliases.
63
+
64
+ ## Controlled Write Path
65
+
66
+ `redctx_submit_doc` is hidden unless the server starts with `--enable-writes`.
67
+ When enabled, it accepts generated redacted text, rebuilds the local
68
+ rehydration map from the private source root, rejects unresolved placeholders,
69
+ and writes the restored document only under `--write-subdir`.
70
+
71
+ The write tool does not accept arbitrary workspace file paths. It accepts text
72
+ content directly and a relative target path. Overwrites require an explicit
73
+ `overwrite` argument. Tool results return only redacted path metadata and opaque
74
+ ids.
75
+
76
+ No-overwrite writes are published from a same-directory temporary file without
77
+ replacing an existing target where hard-link publication is available. Explicit
78
+ overwrites use same-directory `os.replace`. Directory durability fsync is
79
+ best-effort and POSIX-only.
80
+
81
+ ## Redaction Model
82
+
83
+ Redaction combines configured exact terms with conservative generic patterns:
84
+
85
+ - configured clients, organizations, people, and sensitive terms;
86
+ - email addresses, URLs, phone numbers, handles, secrets, tokens, common
87
+ personal identifiers, IP addresses, UUIDs, and domains;
88
+ - organization suffix patterns;
89
+ - multi-token proper names;
90
+ - stricter titlecase/acronym handling in `strict` mode.
91
+
92
+ The allow list prevents common public technologies and generic vocabulary from
93
+ being over-redacted. Project-specific allow-list entries belong in the local
94
+ `.agent-context-redactor.toml`, not in source control.
95
+
96
+ Placeholders are deterministic 128-bit HMAC aliases derived from the local
97
+ salt, for example `[PERSON_1a2b3c4d5e6f7890a1b2c3d4e5f60718]`. The same raw
98
+ value maps to the same placeholder for one private config without exposing the
99
+ raw value. Placeholder collisions are detected and fail closed instead of
100
+ building an ambiguous rehydration map.
101
+
102
+ ## Configuration
103
+
104
+ The local `.agent-context-redactor.toml` file is intentionally ignored by git.
105
+ It may contain exact client names, stakeholder names, project codenames, private
106
+ repo names, and token environment variable names.
107
+
108
+ If a config or environment salt is not supplied, the loader creates or reuses a
109
+ random 256-bit vault salt in user-local state. Missing state creates a new
110
+ random salt. Existing empty, malformed, or root-contained state fails closed
111
+ instead of rotating aliases silently. `redctx doctor` reports the salt source.
112
+
113
+ `redctx discover` can draft that file with a local Ollama model. It is a setup
114
+ command for a human operator, not an MCP tool, because its output intentionally
115
+ contains raw sensitive terms.
116
+
117
+ ## GitHub Issue Access
118
+
119
+ GitHub repositories are configured by neutral aliases under
120
+ `[github.repos.<alias>]`. The alias is what the agent sees. Raw owner/repo names
121
+ and author logins are not printed in tool output. Author aliases are HMACs over
122
+ the local vault salt, repo alias, and login so they are not linkable across
123
+ vaults or repo aliases.
124
+
125
+ The GitHub integration is read-only and uses the token environment variable
126
+ named in local config.
127
+
128
+ ## Security Posture
129
+
130
+ This project is a privacy guardrail, not a hard isolation boundary. If the agent
131
+ process can read the private source folder directly, prompts and MCP routing
132
+ are not enough. For stronger enforcement, run the agent as a separate OS user or
133
+ inside a container that cannot access the private folder directly, and expose
134
+ only the redacted MCP server.
@@ -0,0 +1,112 @@
1
+ # Changelog
2
+
3
+ ## 0.7.0
4
+
5
+ Security hardening release.
6
+
7
+ - Never serves the redaction config, configured term files, `.env*`, `*.key`,
8
+ `*.pem`, or `*.crt` through redacted tools, even with `--include-private`.
9
+ - Redacts bare long hex strings (the persisted vault-salt shape) and
10
+ `salt`-keyed assignments as secrets in the default detector profile, closing
11
+ a vault-salt disclosure path.
12
+ - Adds Google API key (`AIza...`) detection to the default secret patterns.
13
+ - Screens user-supplied search regexes for catastrophic-backtracking shapes
14
+ and rejects them; MCP searches now enforce a server-side operation deadline
15
+ checked per file and per matching line.
16
+ - Caps MCP stdio request line size so clients cannot exhaust server memory.
17
+ - Controlled-write rehydration maps no longer scan the write subdirectory,
18
+ preventing agent-written content from poisoning later rehydration.
19
+ - Verifies `redctx_submit_doc` output re-redacts consistently on read-back and
20
+ rejects writes that would leak restored values past redaction boundaries.
21
+ - Refuses non-loopback plain-http Ollama discovery endpoints unless
22
+ `--allow-remote-endpoint` is passed.
23
+ - Truncation no longer splits redaction placeholders mid-token.
24
+ - Matches user-supplied search regexes in an isolated, killable child process
25
+ so catastrophic patterns can never hang the single-threaded server; the
26
+ static backtracking screen now also rejects ambiguous dots, negated
27
+ classes, nested-group hazards, and high-repetition bounded quantifiers.
28
+ - Case-folds never-serve matching so `.ENV`, `server.PEM`, and similar
29
+ case-mangled variants are refused on case-insensitive filesystems, and
30
+ protects an explicit `--config` file like the default config.
31
+ - Redacts salt assignments with short, spaced, or triple-quoted values,
32
+ 256-bit-plus hex runs of any length, and underscore-qualified secret
33
+ assignments such as `DB_PASSWORD=...`; treats configured GitHub
34
+ owner/repo identifiers as redaction terms.
35
+ - Verifies `redctx_submit_doc` output against both strict and balanced
36
+ redaction modes and builds rehydration maps solely from the scanned
37
+ corpus, closing adjacent-placeholder and interactive-read aliasing gaps.
38
+ - Reports an error for oversized unterminated stdio request lines and accepts
39
+ `localhost.` (trailing-dot) Ollama endpoints.
40
+
41
+ ## 0.6.0
42
+
43
+ - Adds dual-era MCP support for stateless protocol version `2026-07-28` while
44
+ preserving the legacy initialization flow through `2025-11-25`.
45
+ - Adds `server/discover`, per-request modern metadata validation, structured
46
+ unsupported-version errors, modern result metadata, and cache hints.
47
+ - Keeps opaque path ids, the redacted content cache, and the persistent vault
48
+ salt independent of MCP protocol sessions.
49
+
50
+ ## 0.5.0
51
+
52
+ - Adds a reusable document-discovery and monotonic TOML-update API plus the
53
+ `redctx discover-update` JSONL CLI for local Git-hook integrations.
54
+ - Rejects discovery values absent from their source document and supports
55
+ fail-closed document-size limits and seed-only config merges.
56
+ - Adds extended-profile detection for common `sp-`, `svc-`, and `sa-` service
57
+ account identifiers.
58
+
59
+ ## 0.4.0
60
+
61
+ - Revalidates stale opaque ids, rejects detected symlink/reparse substitutions,
62
+ and verifies file metadata around content reads where the standard library
63
+ allows.
64
+ - Changes default vault-salt handling so missing state creates and persists a
65
+ new random salt, while malformed or unsafe existing state fails closed instead
66
+ of silently rotating aliases.
67
+ - Adds per-call redaction receipts, bounded operation budgets, and a bounded
68
+ redacted-only MCP resource cache.
69
+ - Preserves line counts when multi-line secrets are redacted before search
70
+ output is split into lines.
71
+ - Speeds ordinary no-match literal searches by using a raw-byte prefilter while
72
+ keeping placeholder-sensitive and regex searches on the full redaction path.
73
+ - Adds security regression tests, UTF-8 stdio handling, SHA-pinned CI actions,
74
+ and CI package validation for the 0.4.0 release.
75
+
76
+ ## 0.3.0
77
+
78
+ - Adds redacted MCP resources with `redctx://p_<id>` URIs alongside the
79
+ existing `redctx_*` tools.
80
+ - Updates MCP protocol support to `2025-11-25` and advertises read-only tool
81
+ annotations with stricter input schemas.
82
+ - Changes path ids to local-salted HMAC ids to make common filename guesses
83
+ harder.
84
+ - Changes placeholders from order-based counters to deterministic HMAC aliases,
85
+ such as `[PERSON_1a2b3c4d]`.
86
+ - Expands generic redaction coverage for secrets, tokens, common personal
87
+ identifiers, IP addresses, UUIDs, and domains.
88
+ - Adds a CLI-only `redctx rehydrate` command for restoring redacted file or
89
+ folder exports locally from the private source root.
90
+ - Adds opt-in MCP `redctx_submit_doc` controlled writes for rehydrating generated
91
+ redacted documents into a configured private-root subdirectory.
92
+ - Fixes `redctx discover --format json`.
93
+ - Handles UTF-8 BOMs in TOML config and text file reads.
94
+ - Adds regression coverage for discovery JSON output, MCP resources, stricter
95
+ tool schemas, salted ids, deterministic placeholders, and redaction leak
96
+ benchmarks.
97
+
98
+ ## 0.1.0
99
+
100
+ - Initial release candidate.
101
+ - Adds `redctx` CLI for redacted local file discovery, read, search, stat, and
102
+ bundle operations.
103
+ - Adds `redctx-mcp` stdio MCP server exposing `redctx_*` tools for coding
104
+ agents.
105
+ - Supports opaque stable path ids, local TOML redaction configuration, and
106
+ no-dependency runtime operation.
107
+ - Adds `redctx discover`, an offline setup command that uses a local Ollama
108
+ model to draft raw redaction terms for human review.
109
+ - Discovery output is generically post-processed to reduce noisy `terms`
110
+ entries and move public/default-allowed technical vocabulary to `allow`.
111
+ - Adds optional redacted GitHub issue access through configured neutral repo
112
+ aliases and MCP tools.
@@ -0,0 +1,56 @@
1
+ # Contributing
2
+
3
+ This project is security-adjacent, so small changes should still be treated with
4
+ care. Keep the package boring, explicit, and easy to audit.
5
+
6
+ ## Local Setup
7
+
8
+ ```sh
9
+ python3 -m pip install -e .
10
+ python3 -m unittest discover -s tests -p 'test_*.py'
11
+ python3 -m py_compile src/redacted_context_mcp/core.py src/redacted_context_mcp/server.py
12
+ ```
13
+
14
+ Optional release tooling:
15
+
16
+ ```sh
17
+ python3 -m pip install -e '.[dev]'
18
+ python3 -m build
19
+ python3 -m twine check dist/*
20
+ ```
21
+
22
+ ## Standards
23
+
24
+ - Keep runtime dependencies at zero unless there is a strong reason to add one.
25
+ - Keep tool output redacted by default and avoid raw paths, owner/repo names,
26
+ author logins, tokens, or sensitive config values.
27
+ - Prefer clear, local functions over framework abstractions.
28
+ - Keep examples neutral. Do not use real client names, employer names,
29
+ stakeholder names, internal project names, or domain-specific customer
30
+ technology defaults in tracked files.
31
+ - Treat `.agent-context-redactor.toml` and generated discovery output as private
32
+ local files.
33
+
34
+ ## Privacy Checks
35
+
36
+ Before publishing or opening a PR, run:
37
+
38
+ ```sh
39
+ rg -n -i '(<your-company>|<client-name>|<private-repo>|<token-prefix>)' .
40
+ ```
41
+
42
+ Substitute terms that are relevant to your environment before running the scan.
43
+ Some placeholders appear intentionally in docs and examples. Replace anything
44
+ that refers to a real organization, client, person, private repo, token, or
45
+ project codename.
46
+
47
+ ## Release Checks
48
+
49
+ At minimum, a release must pass:
50
+
51
+ ```sh
52
+ python3 -m unittest discover -s tests -p 'test_*.py'
53
+ python3 -m py_compile src/redacted_context_mcp/core.py src/redacted_context_mcp/server.py
54
+ python3 -m build
55
+ python3 -m twine check dist/*
56
+ ```
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zoltan Nagy
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.