Skip to main content
Glama
alxark

data-filter-mcp

by alxark

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

Filter bodies are AST-validated against a whitelist. In addition to a curated set of builtins (len, sorted, max, min, 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.

  • 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.

Related MCP server: jq-mcp

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

Available Tools

3 tools
convert_fileA

Apply a registered filter to a source file and save the text output.

Use this tool after register_filter when you want to transform a local json, yaml, or txt file and persist the returned string as UTF-8 text. The destination path must be inside a configured --workdir; unlike run_filter, convert_file refuses to write when no --workdir is configured.

Missing destination parent directories are created automatically. Existing destination files are rejected unless overwrite is true.

Args: filter_id: Identifier returned earlier by register_filter. source_file_path: Absolute path to the source file to load. destination_file_path: Absolute path where result text is saved. file_type: Optional explicit source file type override. overwrite: Whether to replace an existing destination file.

Returns: A structured object describing the written file and filter metadata.

Raises: ValueError: If paths are invalid, workdir is missing, the filter is unknown or expired, destination exists without overwrite, or the filter returns a non-string result. FileNotFoundError: If the source file does not exist.

ParametersJSON Schema
NameRequiredDescriptionDefault
file_typeNoOptional explicit file type override for the source file. If omitted, detected from the source extension.
filter_idYesIdentifier previously returned by register_filter.
overwriteNoIf false (default), fail when destination exists. If true, overwrite the existing destination file.
source_file_pathYesAbsolute path to the source file. Must be inside an allowed --workdir if any are configured.
destination_file_pathYesAbsolute path to the destination file. Must be inside an allowed --workdir. Missing parent directories are created automatically.

Output Schema

ParametersJSON Schema
NameRequiredDescription
file_typeYesEffective loader type used for the source file. One of: json, yaml, txt.
filter_idYesIdentifier of the registered filter that produced this file.
expires_atYesUTC timestamp in ISO 8601 format when this filter expires.
overwrittenYesWhether an existing destination file was replaced.
bytes_writtenYesNumber of UTF-8 bytes written to the destination file.
source_file_pathYesResolved absolute path of the processed source file.
destination_file_pathYesResolved absolute path where the result text was written.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It thoroughly discloses all behavioral traits: writing behavior, workdir requirement, automatic directory creation, overwrite rejection (unless overwrite is true), and specific error conditions (ValueError, FileNotFoundError). No contradictory information.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a clear one-sentence summary, followed by usage context, then parameter explanations, and finally returns/raises. It is structured and relatively concise, though a bit lengthy. Every sentence serves a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, 3 required), high schema coverage (100%), and presence of output schema, the description is complete. It covers purpose, usage, parameter details, return values, and error conditions. No gaps for the agent to make incorrect decisions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value beyond schema: explains that file_type is an optional override, source_file_path must be inside allowed workdir, missing parent directories for destination are created automatically, and overwrite defaults to false. This enhances the agent's understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: 'Apply a registered filter to a source file and save the text output.' It specifies the resources (source file, destination file, filter) and explicitly contrasts with sibling tools by indicating it is used after register_filter and that run_filter is the alternative for non-persistent transformation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance: use after register_filter, for transforming local json/yaml/txt files and persisting output. It also specifies when not to use: 'refuses to write when no --workdir is configured.' It mentions automatic parent directory creation and overwrite behavior, giving clear context for decision-making.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

register_filterA

Validate and register a restricted Python filter for later execution on a local file.

Use this tool first when you want to run custom filtering or transformation logic against a local document. The submitted source code must define exactly one top-level function with this exact signature:

def filter_item(data):

The server loads the target file before execution and passes the loaded document into filter_item(data).

Input document types:

  • JSON files -> parsed JSON value such as dict, list, string, number, boolean, or null

  • YAML files -> parsed YAML value such as dict, list, string, number, boolean, or null

  • TXT files -> list of text lines

The function must return a text result (str). The returned text may contain any format you want, such as plain text, YAML, CSV-like text, or a custom report.

Preloaded standard-library modules (don't try to import them in your functions):

  • json, yaml, re

  • math, statistics, datetime, decimal

  • collections, itertools, functools, operator

  • textwrap, html, base64, hashlib, ipaddress, unicodedata, difflib

Safety rules:

  • The code is validated against a restricted Python subset

  • Imports, network access, dynamic execution, and unsafe attribute access are rejected

  • Registered filters are stored in memory only and expire automatically after a server-side TTL

Forbidden:

  • Using non-standard libraries or modules

  • Accessing the filesystem, network, or environment variables

  • Defining multiple top-level functions, classes, or module-level code

  • Using dynamic features like eval, exec, or import

Args: code: Python source code that defines exactly one function named filter_item(data).

Returns: A structured object containing the new filter identifier, expiration timestamp, TTL in seconds, and validation policy version.

Raises: ValueError: If the code is invalid, unsafe, or does not match the required function signature.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYesPython source code that defines exactly one top-level function named filter_item(data). The function receives the loaded document and must return a text result.

Output Schema

ParametersJSON Schema
NameRequiredDescription
filter_idYesUnique filter identifier to pass into run_filter.
expires_atYesUTC timestamp in ISO 8601 format when the filter expires.
ttl_secondsYesServer-side lifetime of the registered filter in seconds.
policy_versionYesValidation policy version used for the submitted filter code.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavioral traits: validation, restricted Python subset, preloaded modules, safety rules, expiration via TTL, and forbidden actions. This is comprehensive beyond what annotations typically provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with sections but somewhat lengthy for a tool with one parameter. However, each section adds necessary clarity for a complex tool, so it earns a 4 for being appropriately detailed without bloat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (Python code validation, constraints, multiple input types), the description covers all essential aspects: usage order, function signature, input handling, safety rules, and return format. Complete even with output schema present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (single param 'code'), but description adds rich semantics: explains the code must define filter_item, specifies function signature, input types, and required return type. This significantly enhances the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it validates and registers a restricted Python filter for later execution on a local file. It distinguishes from siblings by explicitly saying 'Use this tool first' and contrasts with run_filter.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: 'Use this tool first when you want to run custom filtering or transformation logic against a local document.' It implies when not to use (for execution, use run_filter) and gives alternative context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_filterA

Run a previously registered filter on a local file and return its text output.

Use this tool after register_filter. The server resolves the registered filter, loads the file from the local filesystem, converts it into an in-memory document, calls filter_item(data), and returns the exact text produced by the filter.

Supported file types:

  • json

  • yaml

  • txt

If file_type is omitted, the server tries to detect the type from the file extension.

File loading behavior:

  • json -> parsed JSON value

  • yaml -> parsed YAML value

  • txt -> list of lines

Args: filter_id: Identifier returned earlier by register_filter. file_path: Path to the local file that should be loaded and passed into the filter. file_type: Optional explicit file type override. Use this when extension-based detection is missing or ambiguous.

Returns: A structured object containing the filter identifier, resolved file path, effective file type, filter expiration time, and result_text.

Raises: ValueError: If the filter does not exist, has expired, returns a non-string result, or the file type is unsupported. FileNotFoundError: If the file does not exist.

ParametersJSON Schema
NameRequiredDescriptionDefault
file_pathYesPath to the local file that should be loaded and passed into filter_item(data).
file_typeNoOptional explicit file type override. If omitted, the server detects the type from the file extension.
filter_idYesIdentifier previously returned by register_filter.

Output Schema

ParametersJSON Schema
NameRequiredDescription
file_pathYesResolved absolute path of the processed local file.
file_typeYesEffective loader type used for the file. One of: json, yaml, txt.
filter_idYesIdentifier of the registered filter that produced this result.
expires_atYesUTC timestamp in ISO 8601 format when this filter expires.
result_textYesExact text returned by filter_item(data).

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavior: it loads a file, converts to in-memory document, calls filter_item, and returns text. It details file type handling, loading behavior per type, errors (ValueError, FileNotFoundError), and the return structure. This is comprehensive and transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, usage, supported types, behavior, args, returns, raises). Every sentence adds value, though it is slightly verbose. It is front-loaded with purpose, making it easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema (not shown but noted), the description appropriately does not repeat return values. It covers prerequisites (register_filter), file types, loading behavior, errors, and the output structure. It is fully complete for an agent to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value by explaining the file loading behavior per type (e.g., 'json -> parsed JSON value'), which enriches understanding of the file_type and file_path parameters beyond the schema. This extra context justifies a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Run a previously registered filter on a local file and return its text output.' It specifies the action (run), the resource (filter), and the context (on a local file). It also distinguishes from sibling tools by mentioning its dependency on register_filter and the distinct behavior from convert_file.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use this tool after register_filter,' guiding the agent on the correct sequence. It implies the prerequisite without explicitly excluding alternatives, but the context is clear. It does not mention when not to use or compare to convert_file, but the guideline is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 3 tool updatesv0.1.0
    • First observedconvert_file
    • First observedregister_filter
    • First observedrun_filter

TDQS

A4.6/5.0
Disambiguation5/5

Each tool has a unique and clearly defined purpose: register_filter validates and stores a filter, run_filter executes it on a file and returns text, and convert_file executes and saves the result to a file. There is no overlap or ambiguity.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (register_filter, run_filter, convert_file), making the API predictable and easy to navigate.

Tool Count4/5

With only 3 tools, the server is minimal but well-scoped for its purpose of applying custom filters to files. The count is appropriate for a focused utility, though additional management tools (e.g., list_filters) could be added without bloat.

Completeness4/5

The tools cover the essential workflow: register a filter, run it (in-memory output), and convert it (persisted output). Missing are filter listing, deletion, or inspection, but the automatic expiration mitigates the need for explicit management.

Maintenance

ActivityInactive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    A config-driven, zero-dependency MCP server with plugin architecture that enables filesystem operations, shell commands, HTTP requests, and utilities through simple JSON configuration.
    3
    1
    -
  • A
    license
    A
    quality
    D
    maintenance
    An MCP server that exposes a single tool, jq, for running jq filters against JSON files on disk.
    1
    15
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alxark/data-filter-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server