Data Processing in AI Agents: MCP Tools Guide

AI agents that process data need to validate JSON, encode strings, transform formats, and handle structured inputs reliably. LLMs alone are notoriously bad at this. This guide shows how to build robust data processing pipelines using MCP tools.

JSON Validation and Formatting

LLMs frequently produce invalid JSON. They add trailing commas, forget to quote keys, use single quotes, or generate partial responses. Before any agent uses JSON data, it should validate and fix it.

Validate JSON Syntax

Tool Call
json/validate
{
  "json": "{\"name\": \"test\", \"count\": 5,}"
}
Response
{
  "valid": false,
  "error": "Trailing comma at position 31",
  "line": 1,
  "column": 31
}

Prettify JSON

Make JSON readable for debugging or display:

Tool Call
json/prettify
{
  "json": "{\"user\":{\"name\":\"John\",\"email\":\"john@example.com\"},\"active\":true}",
  "indent": 2
}
Response
{
  "formatted": "{\n  \"user\": {\n    \"name\": \"John\",\n    \"email\": \"john@example.com\"\n  },\n  \"active\": true\n}"
}

Minify JSON

Compress JSON for transmission:

Tool Call
json/minify
{
  "json": "{\n  \"name\": \"test\",\n  \"value\": 123\n}"
}
Response
{
  "minified": "{\"name\":\"test\",\"value\":123}",
  "originalSize": 42,
  "minifiedSize": 27,
  "savings": "35.7%"
}
Pro tip: Always validate JSON before passing it to other systems. A single syntax error can cause entire pipelines to fail.

Data Transformation

Agents often need to transform data between formats. TinyFn provides tools for common transformations:

String Case Conversion

Tool Input Output
string/to-camel-case user_first_name userFirstName
string/to-snake-case userFirstName user_first_name
string/to-kebab-case userFirstName user-first-name
string/slugify Hello World! hello-world

URL Slug Generation

Tool Call
string/slugify
{
  "text": "How to Build AI Agents (2025 Guide)"
}
Response
{
  "slug": "how-to-build-ai-agents-2025-guide",
  "original": "How to Build AI Agents (2025 Guide)"
}

Text Truncation

Tool Call
string/truncate
{
  "text": "This is a very long text that needs to be shortened for display purposes",
  "length": 30,
  "suffix": "..."
}
Response
{
  "truncated": "This is a very long text th...",
  "wasTruncated": true,
  "originalLength": 73
}

Encoding/Decoding Pipelines

Agents processing API data frequently need to encode and decode strings. LLMs cannot reliably compute Base64 or URL encodings - they must use tools.

Base64 Encoding

Tool Call
encode/base64
{
  "text": "Hello, World!"
}
Response
{
  "encoded": "SGVsbG8sIFdvcmxkIQ==",
  "original": "Hello, World!"
}

URL Encoding

Tool Call
encode/url
{
  "text": "search query with spaces & special=chars"
}
Response
{
  "encoded": "search%20query%20with%20spaces%20%26%20special%3Dchars",
  "original": "search query with spaces & special=chars"
}

JWT Decoding

Inspect JWT tokens without validation (useful for debugging):

Tool Call
decode/jwt
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
Response
{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "1234567890",
    "name": "John Doe",
    "iat": 1516239022
  },
  "signature": "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}

Batch Processing Patterns

When agents need to process multiple items, batch processing patterns improve efficiency:

Pattern 1: Sequential Validation

Python
async def validate_emails(emails: list[str]) -> dict:
    """Validate a batch of emails."""
    results = {"valid": [], "invalid": []}

    for email in emails:
        response = await tinyfn.call("validate/email", {"email": email})

        if response.get("valid"):
            results["valid"].append(email)
        else:
            results["invalid"].append({
                "email": email,
                "reason": response.get("reason")
            })

    return results

# Usage
emails = ["good@example.com", "invalid-email", "another@test.com"]
results = await validate_emails(emails)
# {"valid": ["good@example.com", "another@test.com"], "invalid": [...]}

Pattern 2: Parallel Processing

Python
import asyncio

async def hash_batch(items: list[str]) -> list[dict]:
    """Hash multiple items in parallel."""
    tasks = [
        tinyfn.call("hash/sha256", {"text": item})
        for item in items
    ]

    results = await asyncio.gather(*tasks)
    return [
        {"original": item, "hash": result["hash"]}
        for item, result in zip(items, results)
    ]

# Usage
items = ["password1", "password2", "password3"]
hashed = await hash_batch(items)

Pattern 3: Transform Pipeline

JavaScript
async function transformPipeline(data) {
  // Step 1: Validate JSON
  const validated = await tinyfn.call("json/validate", { json: data });
  if (!validated.valid) {
    throw new Error(`Invalid JSON: ${validated.error}`);
  }

  // Step 2: Parse and extract
  const parsed = JSON.parse(data);

  // Step 3: Transform fields
  if (parsed.title) {
    const slugged = await tinyfn.call("string/slugify", { text: parsed.title });
    parsed.slug = slugged.slug;
  }

  // Step 4: Encode sensitive data
  if (parsed.secret) {
    const encoded = await tinyfn.call("encode/base64", { text: parsed.secret });
    parsed.secret = encoded.encoded;
  }

  // Step 5: Minify output
  const output = await tinyfn.call("json/minify", { json: JSON.stringify(parsed) });
  return output.minified;
}

Validation Chains

Complex data often requires multiple validations. Chain them for comprehensive checking:

Validation Chain
async function validateUserData(userData) {
  const errors = [];

  // Validate email
  const emailResult = await tinyfn.call("validate/email", {
    email: userData.email
  });
  if (!emailResult.valid) {
    errors.push(`Invalid email: ${emailResult.reason}`);
  }

  // Validate phone
  const phoneResult = await tinyfn.call("validate/phone", {
    phone: userData.phone,
    country: "US"
  });
  if (!phoneResult.valid) {
    errors.push(`Invalid phone: ${phoneResult.reason}`);
  }

  // Validate URL (if provided)
  if (userData.website) {
    const urlResult = await tinyfn.call("validate/url", {
      url: userData.website
    });
    if (!urlResult.valid) {
      errors.push(`Invalid website URL: ${urlResult.reason}`);
    }
  }

  // Check password strength
  const passwordResult = await tinyfn.call("password/analyze", {
    password: userData.password
  });
  if (passwordResult.score < 3) {
    errors.push(`Weak password: ${passwordResult.feedback}`);
  }

  return {
    valid: errors.length === 0,
    errors
  };
}

Implementation Guide

Setting Up for Data Processing

mcp.json
{
  "mcpServers": {
    "tinyfn-data": {
      "url": "https://api.tinyfn.io/mcp/json",
      "headers": { "X-API-Key": "your-api-key" }
    },
    "tinyfn-encode": {
      "url": "https://api.tinyfn.io/mcp/encode/",
      "headers": { "X-API-Key": "your-api-key" }
    },
    "tinyfn-validate": {
      "url": "https://api.tinyfn.io/mcp/validate/",
      "headers": { "X-API-Key": "your-api-key" }
    },
    "tinyfn-string": {
      "url": "https://api.tinyfn.io/mcp/string/",
      "headers": { "X-API-Key": "your-api-key" }
    }
  }
}

Build Reliable Data Pipelines

Stop letting LLMs corrupt your data. Use deterministic processing tools.

Get Free API Key

Ready to try TinyFn?

Get your free API key and start building in minutes.

Get Free API Key