Install
$ agentstack add mcp-231self-maskura ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Maskura
Maskura is a privacy boundary between agents and object data. It sits in front of your existing S3-compatible storage and redacts or encrypts sensitive data on the way through, so agents get the view you allow and the raw object never leaves your bucket.
Read path — agents see the view you allow; the raw object stays in storage.
Write path — protection is applied before the object reaches storage.
- Pluggable pipeline — plugins run in order; each can emit, drop, or reject. A tiny
WIT interface (begin / transform / finish), pure byte-in/byte-out.
- Sandboxed — wasmtime, 64 MiB memory, fuel-limited, no host imports.
- BYO plugins — write in Rust (or any Wasm-capable language), wrap with
wasm-tools component, maskura plugin upload. See [docs/plugins.md](docs/plugins.md).
- Any S3-compatible storage — MinIO, AWS S3, Google Cloud Storage, Backblaze B2,
Cloudflare R2, Vultr Object Storage — single or multi-cloud (consistent-hash ring, dual-write, read fail-over). MinIO is covered by the CI end-to-end suite; Backblaze B2 is tested against a real bucket (redaction and envelope-encryption round-trips).
- Agent-safe reads — read data through Maskura with
x-maskura-process: read: the pipeline
runs on the way out, so AI agents get redacted/encrypted output while the object at rest stays raw. No second cleaned copy to keep in sync.
- Optional auth — run with auth disabled locally, or enable API keys (in-memory,
a JSON file, or Postgres).
- Typed SDKs — generated Python and TypeScript clients, published with every release.
Filters shipped in-tree (as examples to learn from): noop, pii-default (redact emails / SSNs / credit cards), email-detect, ssn-detect, card-detect, envelope-encrypt (per-field RSA-OAEP / AES-256-GCM), stable-encrypt (deterministic encryption).
Contents
- [Quickstart](#quickstart)
- [Install the CLI (optional)](#install-the-cli-optional)
- [Compatibility](#compatibility)
- [Run your own plugin](#run-your-own-plugin)
- [Usage examples](#usage-examples)
- [Demo](#demo)
- [How it works](#how-it-works)
- [Development](#development)
- [Security](#security)
- [Documentation](#documentation)
- [LLM agents](#llm-agents)
- [License](#license)
Quickstart
No cloud account, no database, no repo clone — run the published image:
docker run --rm -p 127.0.0.1:8791:8080 \
-e AUTH_DISABLED=true \
-e MASKURA_STREAMING_READ_MODE=passthrough \
ghcr.io/231self/maskura/maskura:latest
# open http://localhost:8791 → demo dashboard (no sign-up)
The gateway speaks SigV4, so your existing aws s3 CLI works as-is:
export AWS_ACCESS_KEY_ID=demo AWS_SECRET_ACCESS_KEY=demo
printf '{"email":"jane@example.com","card":"4111111111111111"}\n' > data.jsonl
# Write through the pipeline; pii-default redacts on the way in:
aws s3 --endpoint-url http://localhost:8791 \
cp data.jsonl s3://s4-local/ingest/data.jsonl --content-type application/x-ndjson
# Read it back:
aws s3 --endpoint-url http://localhost:8791 cp s3://s4-local/ingest/data.jsonl -
# → {"email":"[REDACTED_EMAIL]","card":"[REDACTED_CARD]"}
curl works too — x-maskura-* headers are the non-SigV4 alternative:
echo "jane.doe@example.com 4111111111111111" > data.txt
curl -X PUT http://localhost:8791/s4-local/ingest/data.txt \
-H "Content-Type: text/plain" --data-binary @data.txt
curl http://localhost:8791/s4-local/ingest/data.txt
# → [REDACTED_EMAIL] [REDACTED_CARD]
We map the container's 8080 to 8791 on your host so it doesn't collide with anything you already run. The dashboard's copy-paste snippets use whatever host:port you opened, so they just work.
Install the CLI (optional)
Prefer the CLI? Install it with cargo install, or grab the prebuilt Linux (amd64/arm64) binaries attached to each GitHub Release:
cargo install --git https://github.com/231self/maskura --bin maskura s4ctl
maskura local init # runs the published gateway image (Docker)
maskura plugin list # the pii-default plugin is preloaded
# A sample file to push through the pipeline:
echo "jane.doe@example.com 4111111111111111" > data.csv
# Write data through the pipeline; it is transformed before it reaches storage
maskura put ./data.csv ingest/data.csv --bucket s4-local
# Read it back
maskura get ingest/data.csv --bucket s4-local
maskura local init pulls the gateway image tagged with the CLI version (ghcr.io/231self/maskura/maskura:v0.4.1 for maskura 0.4.1; CLI and gateway always match, never :latest) and runs it in local mode (AUTH_DISABLED=true, keys persisted on a volume, in-memory storage); it picks a free port (8080+) and only listens on localhost. maskura local down stops it. For durable local storage (MinIO), clone the repo and use just dev-up.
Compatibility
New integrations should use MASKURA_* environment variables and x-maskura-* headers. The s4ctl and s4-mcp binaries, s4_* MCP tools, s4_client Python module, and S4Client SDK exports remain available.
Persistent and security-sensitive identifiers do not change: credentials still use s4_/s4s_/s4m_, local CLI state remains under ~/.config/s4, existing container/volume names remain shared, WIT namespaces remain s4:*, stored metadata remains s4-*, and legacy images remain pullable from ghcr.io/231self/s4/s4.
Run your own plugin
# 1. Write a filter (Rust + wit-bindgen against wit/s4-filter/world.wit)
# 2. Build it:
cargo build --release --target wasm32-unknown-unknown
wasm-tools component new target/wasm32-unknown-unknown/release/my_filter.wasm \
-o my-filter.component.wasm
# 3. Upload and enable it:
maskura plugin upload my-filter.component.wasm
maskura plugin enable
# 4. Reorder the pipeline — output of one feeds the next:
maskura plugin reorder pii-default my-filter
Full guide: [docs/plugins.md](docs/plugins.md).
Typed binary codecs use a separate schema-aware reductor contract, not the byte-oriented plugin pipeline. See [docs/binary-adapters.md](docs/binary-adapters.md) when adding a custom logical-type adapter.
Opt-in Avro OCF processing (MASKURA_ENABLE_AVRO=true) and its supported subset are documented in [docs/avro.md](docs/avro.md). A runnable PUT/read example is in [examples/avro-demo.py](examples/avro-demo.py).
The local stdio MCP server exposes put, get, list, and delete tools to agent clients while preserving the gateway's normal auth, pipeline, and metering path. See [docs/mcp.md](docs/mcp.md) for Claude Desktop, Cursor, and Kilo setup, plus the runnable [examples/mcp-client.py](examples/mcp-client.py) lifecycle.
Usage examples
Everything below is copy-paste runnable.
Redaction — PII filtered on write
# Local gateway (published image, Docker, in-memory storage):
maskura local init
maskura put ./data.csv ingest/data.csv --bucket s4-local
maskura get ingest/data.csv --bucket s4-local # emails/SSNs/cards redacted
# Durable local storage (MinIO) from a repo clone:
just dev-up
maskura put ./data.csv ingest/data.csv --bucket s4-local
# End-to-end validation:
just e2e # see docs/e2e.md for the feature-by-feature breakdown
Agent-safe reads — raw at rest, scrubbed on the way out
# Data at rest stays raw (your app owns the originals).
maskura put ./customers.json customers/c1.json --bucket s4-local
# Transformed reads are deliberately opt-in. Unsafe component snapshots are
# staged encrypted before any response bytes are disclosed.
export MASKURA_STREAMING_READ_MODE=transformed
export MASKURA_TRANSFORMED_READ_SPOOL=encrypted
# Set this to the SHA-256 component digests reviewed for prefix-safe disclosure.
# Imported components are unsafe unless listed here.
export MASKURA_PREFIX_SAFE_COMPONENT_HASHES=
# An AI agent reads through Maskura: PII is redacted before the agent sees it.
curl -H "x-maskura-process: read" http://localhost:8080/customers/c1.json
# → {"email":"[REDACTED_EMAIL]","card":"[REDACTED_CARD]","note":"hi"}
# Same object, no header: the raw bytes your app owns.
curl http://localhost:8080/customers/c1.json
# → {"email":"alice@example.com","card":"4111111111111111","note":"hi"}
One source of truth, two projections: the app gets full fidelity, the agent gets only what you allow. Transformed reads require stored, version-bound metadata and work with S3, managed storage, and in-memory backends. Presigned backend URLs remain raw-only because they cannot provide a safe metadata preflight.
Transformed reads reject Range, partNumber, non-identity source encodings, unknown mandatory formats, and HEAD. They never fall back to raw bytes. MASKURA_STREAMING_READ_MODE=off (the default) rejects transformed reads; passthrough enables only raw streaming. transformed enables this path. Without MASKURA_TRANSFORMED_READ_SPOOL=encrypted, a snapshot containing any component not listed in MASKURA_PREFIX_SAFE_COMPONENT_HASHES is rejected before its source body is consumed. Set MASKURA_SPOOL_DIR, MASKURA_SPOOL_MAX_OBJECT_BYTES, and MASKURA_SPOOL_QUOTA_BYTES to a private, capacity-reserved volume; the quota must cover encrypted framing overhead as well as plaintext output.
Encryption — per-field envelope encryption, decryptable only by you
# Round-trip against any S3-compatible bucket: pre-encrypt fixture →
# encrypted bytes fetched straight from the bucket → decrypted through Maskura:
export B2_S3_ENDPOINT=https://s3.us-east-005.backblazeb2.com
export B2_REGION=us-east-005
export B2_BUCKET=your-bucket
export B2_ACCESS_KEY_ID=your-key-id
export B2_SECRET_ACCESS_KEY=your-application-key
bash examples/b2-encrypt-demo.sh
Plugins — bring your own transform
maskura plugin list # pipeline order
maskura plugin upload my-filter.component.wasm # runtime import, no rebuild
maskura plugin enable
maskura plugin reorder pii-default my-filter # output of one feeds the next
SDKs — Python
from maskura_client import MaskuraClient
client = MaskuraClient("http://localhost:8080", "s4_access_key", "s4s_secret_key")
priv, pub = client.generate_keypair() # RSA-2048
client.attach_public_key(pub) # bind to your API key
client.put_object("bucket", "key", b"jane@example.com 4111111111111111")
blob = client.get_object("bucket", "key")
assert "jane@example.com" not in blob.decode() # stored encrypted
print(client.decrypt_payload(blob, priv)) # you hold the key
Full details: [examples/README.md](examples/README.md) and [docs/plugins.md](docs/plugins.md).
Demo
The same PII file, three ways — raw, redacted, and deterministic-encrypted — pushed through aws s3 pointed at Maskura. Watch the interactive demo (pause, scrub, speed) →
How it works
S3 SDK / CLI / tool ──▶ Maskura Gateway (Wasm plugin pipeline) ──▶ storage
│
├─ filter → redact emails, SSNs, credit cards
├─ encrypt → per-field envelope / deterministic encryption
└─ ... → your plugins, in order
Development
just check # fmt + clippy + build filters + tests
just e2e # end-to-end against MinIO (Docker)
just build-sdks # regenerate Python/TypeScript SDKs from the OpenAPI spec
Run CI/release locally (no GitHub minutes)
Two local pipeline runners, both with persistent caches:
just ci-local— runs the real.github/workflows/ci.ymlvia
act (local Docker; actions/cache backed by act's cache server, so cargo deps are reused across runs).
just build-local/just image-local/just publish-local TAG=x— dagger
pipeline (dagger/main.py) with cargo registry + target dirs on persistent cache volumes; publish-local pushes identical canonical and legacy tags to ghcr.io/231self/maskura/maskura and ghcr.io/231self/s4/s4 (needs docker login ghcr.io once).
See CONTRIBUTING.md.
Security
Maskura transforms sensitive data before it reaches storage and applies strict, fail-closed guarantees on the streaming data plane. See [docs/security.md](docs/security.md) for the full model — what's guaranteed and what's on you.
Found a vulnerability? Report it privately — via Maskura private vulnerability reporting or security@231self.com — and never through a public issue. See [SECURITY.md](SECURITY.md) for the supported-version policy, response timeline, and what to include in a report.
Documentation
- Docs site — the same docs, rendered:
.
examples/— runnable end-to-end demos (B2 encryption round-trip).docs/plugins.md— create and consume your own plugins.docs/security.md— the security model of the gateway.docs/adr/— architecture decision records.AGENTS.md— development conventions.CONTRIBUTING.md— contribution guide, tests, and author identity policy.OWNERS.md— maintainers and decision process.
LLM agents
Coding agents (Claude Code, Kilo, Cursor, …) read AGENTS.md from the repo root automatically. For project-specific Maskura context, install the bundled skill:
# Claude Code (user-global):
mkdir -p ~/.claude/skills && ln -s "$(pwd)/skills/maskura" ~/.claude/skills/maskura
# Kilo (user-global):
mkdir -p ~/.kilo/skills && ln -s "$(pwd)/skills/maskura" ~/.kilo/skills/maskura
The skill teaches agents what Maskura is, the plugin pipeline, build/test/run commands, crate layout, and the CI/release gotchas (BuildKit cache mounts, act/colima, multi-arch builds).
License
Apache-2.0. See LICENSE.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: 231self
- Source: 231self/maskura
- License: Apache-2.0
- Homepage: https://maskura.dev
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.