Skip to main content

data-filter-mcp

Local MCP server that registers restricted Python filters and runs them against local json, yaml, and txt files.

What it does

  • register_filter accepts Python source code with exactly one top-level function: def filter_item(data):
  • run_filter loads a local file, passes the loaded document into filter_item(data), and returns the text from result_text
  • convert_file loads a local file, passes it into filter_item(data), and writes the returned text to another local file
  • Registered filters live only in memory and expire automatically based on server TTL settings

What filter code may use

Allowed modules are preloaded into the filter namespace. Redundant import json, import math, re, and import datetime as dt statements are accepted at module level and inside functions. They are removed before validation and execution (aliases remain available); no actual imports are executed. Imports of other modules, dotted module names, and all from ... import ... forms remain rejected. All other validation rules still apply, including the single top-level function requirement. Imports are unnecessary; prefer using the preloaded canonical names.

Filter bodies are AST-validated against a whitelist. In addition to a curated set of builtins (len, sorted, max, min, next, range, enumerate, zip, sum, any, all, conversions, etc.) and safe string/dict/list methods, filters may also use a curated set of standard-library modules. Modules are exposed by their canonical names (math, datetime, hashlib, etc.). Filesystem, process, network, and unsafe serialization modules (os, pathlib, shutil, subprocess, socket, urllib, pickle, etc.) are intentionally not available.

Filters support next(generator) and next(generator, default), as well as assert statements (with optional messages) and catching AssertionError. Assertions are disabled when the server runs with Python optimization (-O or -OO); do not use optimized mode when relying on assertions for validation.

  • lambda expressions — typically as key= arguments, e.g. sorted(data, key=lambda item: item.get("score")). Lambda bodies are validated by the same rules as the rest of the filter.
  • jsonjson.loads, json.dumps.
  • yamlyaml.safe_load, yaml.safe_dump. The unsafe yaml.load / yaml.dump are intentionally not exposed.
  • rere.match, re.search, re.fullmatch, re.findall, re.sub, re.subn, re.compile, re.escape, plus Match / Pattern methods (group, groups, groupdict, start, end, span).
  • math — numeric helpers such as math.ceil, math.floor, math.sqrt, math.log, math.exp, math.pow, math.factorial, math.gcd, math.lcm, math.isfinite, math.isclose.
  • statistics — aggregates such as statistics.mean, statistics.median, statistics.stdev, statistics.variance, statistics.quantiles.
  • datetimedatetime.datetime.fromisoformat, datetime.datetime.now, datetime.timedelta, datetime.timezone.utc, and instance methods such as isoformat, strftime, timestamp, weekday, total_seconds. General instance attribute reads such as dt.year and dt.month are not supported by the current policy.
  • decimaldecimal.Decimal(...), quantize, normalize, to_eng_string, to_integral_value.
  • collectionscollections.Counter, collections.defaultdict, collections.OrderedDict, collections.deque, plus methods such as most_common, elements, popleft, appendleft, rotate.
  • itertoolschain, chain.from_iterable, islice, takewhile, dropwhile, groupby, starmap, accumulate, combinations, permutations, product, filterfalse.
  • functoolsreduce, partial, cmp_to_key, wraps. Caching decorators such as lru_cache and cache are intentionally not exposed because they can retain process-local state across filter calls.
  • operatoritemgetter, methodcaller, and arithmetic/comparison helpers such as add, mul, lt, eq, gt. attrgetter is intentionally not exposed.
  • textwrapfill, wrap, shorten, indent, dedent.
  • htmlhtml.escape, html.unescape.
  • base64b64encode, b64decode, urlsafe_b64encode, urlsafe_b64decode, b32encode, b32decode, b16encode, b16decode.
  • hashlibhashlib.sha256, hashlib.sha1, hashlib.md5, hashlib.blake2b, hashlib.new, plus hash object methods such as hexdigest, digest, update.
  • ipaddressip_address, ip_network, ip_interface, IPv4Network, IPv6Network, plus methods such as supernet, subnets, hosts, overlaps, subnet_of, supernet_of. General instance attribute reads such as addr.is_private and addr.compressed are not supported by the current policy.
  • unicodedatacategory, name, lookup, numeric, digit, decimal, bidirectional, combining, mirrored.
  • difflibget_close_matches, ndiff, unified_diff, context_diff, SequenceMatcher.

Note: re.compile runs against patterns supplied by filter code, so a pathological pattern can stall the server (ReDoS). Some helpers such as difflib.SequenceMatcher can also be CPU-heavy on large inputs. Treat filter source as trusted-but-restricted.

Run with uvx

After publishing to PyPI, start the server with:

uvx data-filter-mcp --filter-ttl-seconds 3600 --cleanup-interval-seconds 60

Show the available CLI flags with:

uvx data-filter-mcp --help

Restricting file access with --workdir

By default the server can read any file on the local filesystem. Use one or more --workdir flags to restrict file reads to specific directories:

uvx data-filter-mcp \
  --filter-ttl-seconds 3600 \
  --cleanup-interval-seconds 60 \
  --workdir /Users/me/project \
  --workdir /tmp/data

Rules:

  • Each --workdir value must be an absolute path to an existing directory.
  • run_filter will only accept files located inside the allowed directories.
  • If no --workdir flags are provided, no restrictions are applied (backward compatible).
  • convert_file always requires at least one --workdir because it writes to disk.
  • convert_file requires the destination path to be inside an allowed workdir.
  • convert_file creates missing destination parent directories automatically.
  • convert_file refuses to replace an existing destination file unless overwrite is true.

Writing transformed files with convert_file

Use convert_file when the filtered output should be persisted instead of returned inline to the model. The tool accepts:

  • filter_id — an identifier returned by register_filter
  • source_file_path — absolute path to the json/yaml/txt file to load
  • destination_file_path — absolute path where the returned text should be saved
  • file_type — optional source file type override (json, yaml, or txt)
  • overwrite — optional boolean, default false

Example flow:

def filter_item(data):
    return "\n".join(data["items"])

Then call convert_file with a source such as /tmp/data/items.json and a destination such as /tmp/data/out/items.txt. The result is written as UTF-8 text. The returned metadata includes the resolved source and destination paths, the effective source file type, bytes_written, and whether an existing file was overwritten.

Example MCP client configuration:

{
  "mcpServers": {
    "data-filter": {
      "command": "uvx",
      "args": [
        "data-filter-mcp",
        "--filter-ttl-seconds",
        "3600",
        "--cleanup-interval-seconds",
        "60",
        "--workdir",
        "/Users/me/project",
        "--workdir",
        "/tmp/data"
      ]
    }
  }
}

Run locally

python server.py --filter-ttl-seconds 3600 --cleanup-interval-seconds 60
python -m data_filter_mcp.server --filter-ttl-seconds 3600 --cleanup-interval-seconds 60
.venv/bin/data-filter-mcp --filter-ttl-seconds 3600 --cleanup-interval-seconds 60

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

data_filter_mcp-0.2.9.tar.gz (31.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

data_filter_mcp-0.2.9-py3-none-any.whl (21.6 kB view details)

Uploaded Python 3

File details

Details for the file data_filter_mcp-0.2.9.tar.gz.

File metadata

  • Download URL: data_filter_mcp-0.2.9.tar.gz
  • Upload date:
  • Size: 31.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for data_filter_mcp-0.2.9.tar.gz
Algorithm Hash digest
SHA256 8ceaa7118a208e72a6e79c1d7ee9a5f2d65d94c2b7814255158947a7571f68be
MD5 8b07add8fb4f89ae3ddf9799e6bd2044
BLAKE2b-256 e3f429921aae9abd5b6b9c53182f95c08a7951324d48ec682a6b68aa07fcb5a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for data_filter_mcp-0.2.9.tar.gz:

Publisher: release.yml on alxark/data-filter-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file data_filter_mcp-0.2.9-py3-none-any.whl.

File metadata

File hashes

Hashes for data_filter_mcp-0.2.9-py3-none-any.whl
Algorithm Hash digest
SHA256 3cf44e5c816736f0bb927dbe7a83d3e7e13b22ffded08337b15cdc6860f54fef
MD5 4cd86001fe04d7aecf5228837aa261f2
BLAKE2b-256 5200d8590be21748e9cfa8ec1c5a5991449fde2f24969aa12ed4f409aa2a2566

See more details on using hashes here.

Provenance

The following attestation bundles were made for data_filter_mcp-0.2.9-py3-none-any.whl:

Publisher: release.yml on alxark/data-filter-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.9 This release

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page