Skip to main content

Reference validators for autonomous systems protocols: MCP, A2A, ACE, OCC/OCS/OCP

Project description

Preflight Tools

Reference validators for autonomous systems protocols: MCP, A2A, ACE, OCC/OCS/OCP

License Python 3.10+

Overview

Preflight Tools provides reference implementations for protocol compliance validation across autonomous agent ecosystems. These validators catch common integration issues before deployment, saving hours of debugging.

Supported Protocols

  • MCP (Model Context Protocol) - Anthropic's protocol for LLM tool integration
  • A2A (Agent-to-Agent) - Peer communication protocol for autonomous agents
  • ACE (Autonomic Compliance Ecosystem) - Platform orchestration standards
  • OCC/OCS/OCP - (Coming soon) Observability, compliance, and policy protocols

Installation

# Via pip
pip install preflight-tools

# Via Poetry
poetry add preflight-tools

# From source
git clone https://github.com/syzygysys/preflight-tools.git
cd preflight-tools
poetry install

Quick Start

MCP Validation

Validate your MCP server implementation against the specification:

# Validate a tools definition file
mcp-preflight-check validate path/to/tools.py

# Test a running server
mcp-preflight-check test http://localhost:8000

# Full report with verbose output
mcp-preflight-check validate --verbose path/to/tools.py

Example output:

✅ Tool names: All valid [a-zA-Z0-9_-]
✅ Properties schemas: All using objects {}
✅ Content wrappers: All responses properly wrapped
✅ Notification handling: Correctly implemented
✅ JSON-RPC structure: All responses include required fields
❌ Stdout pollution: Found 3 print statements that will break stdio transport

Fix suggestions:
  Line 42: Remove print() statement
  Line 89: Use logging instead of print()
  Line 134: Redirect to stderr

A2A Validation

(Coming soon) Validate Agent-to-Agent protocol implementations:

a2a-preflight-check validate path/to/agent_config.yml

The Six Critical MCP Fixes

This validator is built from real-world debugging of LAP::CORE's MCP integration. See the full story: Debugging the Bridge

1. Tool Name Pattern

Problem: Tool names with dots fail Zod validation
Rule: Must match ^[a-zA-Z0-9_-]{1,64}$

# ❌ FAILS
{"name": "lap.health.ping"}

# ✅ PASSES
{"name": "lap_health_ping"}

2. Properties Schema Type

Problem: Empty properties as [] instead of {}
Rule: JSON Schema requires properties to be an object

# ❌ FAILS
{
    "inputSchema": {
        "type": "object",
        "properties": []  # Wrong type
    }
}

# ✅ PASSES
{
    "inputSchema": {
        "type": "object",
        "properties": {}  # Correct type
    }
}

3. Content Wrapper Structure

Problem: Returning raw data instead of MCP content structure
Rule: All responses must be wrapped

# ❌ FAILS
return {"status": "ok", "value": 42}

# ✅ PASSES
return {
    "content": [{
        "type": "text",
        "text": json.dumps({"status": "ok", "value": 42})
    }]
}

4. Notification Handling

Problem: Returning errors for notification requests (no id field)
Rule: Notifications don't expect responses

# ❌ FAILS
async def dispatch(self, request: dict) -> str:
    method = request.get("method")
    if method not in self.handlers:
        return json.dumps({"error": "unknown method"})

# ✅ PASSES
async def dispatch(self, request: dict) -> str:
    # Check if this is a notification (no "id" field)
    if "id" not in request:
        return ""  # Silent success
    
    method = request.get("method")
    # ... handle request-response

5. Stdout Pollution

Problem: Any output to stdout breaks JSON-RPC stdio transport
Rule: Redirect stderr early, never use print()

# ❌ FAILS - stderr goes to stdout
poetry run mcp-server 2>> /tmp/debug.log

# ✅ PASSES - redirect before Python starts
exec 2>/tmp/debug.log; poetry run mcp-server

In code:

# ❌ NEVER
print("Debug message")

# ✅ ALWAYS
import logging
logging.error("Debug message")  # Goes to stderr

6. JSON-RPC Response Structure

Problem: Using exclude_none=True removes required fields when they're None
Rule: JSON-RPC 2.0 requires id and jsonrpc in every response

# ❌ FAILS - removes 'id' when it's None
class JsonRpcResponse(BaseModel):
    jsonrpc: str = "2.0"
    id: Optional[Any] = None
    result: Optional[Any] = None
    error: Optional[Dict[str, Any]] = None
    
    def json(self, **kwargs):
        return self.model_dump_json(exclude_none=True, **kwargs)

# ✅ PASSES - keeps required fields
class JsonRpcResponse(BaseModel):
    jsonrpc: str = "2.0"
    id: Optional[Any] = None
    result: Optional[Any] = None
    error: Optional[Dict[str, Any]] = None
    
    def json(self, **kwargs):
        data = self.model_dump()
        # Keep id and jsonrpc always, only exclude result/error conditionally
        if data.get('error') is not None:
            data.pop('result', None)
        elif data.get('result') is not None:
            data.pop('error', None)
        return json.dumps(data)

API Usage

Python API

from preflight_tools.mcp import MCPValidator

validator = MCPValidator()

# Validate a tools file
results = validator.validate_file("path/to/tools.py")

for issue in results.issues:
    print(f"{issue.severity}: {issue.message}")
    print(f"  Fix: {issue.suggestion}")

# Test a running server
results = validator.test_server("http://localhost:8000")
print(f"Protocol version: {results.protocol_version}")
print(f"Tools found: {len(results.tools)}")

Configuration

Create a .preflight.toml in your project root:

[mcp]
strict = true  # Fail on warnings
ignore = ["stdout-pollution"]  # Skip specific checks

[a2a]
version = "0.1.0"
require_auth = true

Development

# Clone and setup
git clone https://github.com/syzygysys/preflight-tools.git
cd preflight-tools
poetry install

# Run tests
poetry run pytest

# Run validator on itself
poetry run mcp-preflight-check validate src/

# Format and lint
poetry run black src/ tests/
poetry run ruff check src/ tests/
poetry run mypy src/

Architecture

preflight-tools/
├── src/preflight_tools/
│   ├── mcp/              # MCP validation
│   │   ├── validator.py  # Core validation logic
│   │   ├── checks.py     # Individual check implementations
│   │   └── cli.py        # Command-line interface
│   ├── a2a/              # A2A validation (coming soon)
│   └── common/           # Shared utilities
├── tests/
│   ├── test_mcp.py
│   └── fixtures/         # Test cases
└── docs/
    └── protocols/        # Protocol specs

Contributing

We welcome contributions! This is a reference implementation for the community.

  1. Fork the repo
  2. Create a feature branch
  3. Add tests for new validators
  4. Submit a PR with clear description

See CONTRIBUTING.md for details.

Related Projects

References

License

Apache License 2.0 - See LICENSE for details.

Copyright 2025 SyzygySys

Support


Built with ❤️ as a gift to the autonomous systems community.

Project details


Download files

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

Source Distribution

preflight_tools-0.1.1.tar.gz (30.6 kB view details)

Uploaded Source

Built Distribution

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

preflight_tools-0.1.1-py3-none-any.whl (39.0 kB view details)

Uploaded Python 3

File details

Details for the file preflight_tools-0.1.1.tar.gz.

File metadata

  • Download URL: preflight_tools-0.1.1.tar.gz
  • Upload date:
  • Size: 30.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.3.2 CPython/3.12.3 Linux/6.8.0-106-generic

File hashes

Hashes for preflight_tools-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a008cdd40d17e74a5d0e57b6bc58559d333f01fb454fb94113a3a6a1c3294ce1
MD5 5efd8a29f414a17542dff4c2f10c7905
BLAKE2b-256 1a2e985d0cd3f3d24bbef33e8e1cac673467e9339e82b00eef7134f14059bef4

See more details on using hashes here.

File details

Details for the file preflight_tools-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: preflight_tools-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 39.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.3.2 CPython/3.12.3 Linux/6.8.0-106-generic

File hashes

Hashes for preflight_tools-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c98259e8f7ffe7cf5da904a609ce78577ddf02c5e0d568faed96825c1b6364fd
MD5 11f249f5057bf8bdcecf78d9dadd561e
BLAKE2b-256 06c42c82df3f6cd8a3a1c6580a0817f4ce6733188d5fa77d5b0b5f9b06b7d336

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page