ftl-sdk


Nameftl-sdk JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
SummaryPython SDK for building MCP tools that compile to WebAssembly
upload_time2025-08-04 03:54:29
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseApache-2.0
keywords ftl mcp wasm webassembly spin fermyon model-context-protocol
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # ftl-sdk (Python)

Python SDK for building Model Context Protocol (MCP) tools that compile to WebAssembly.

[![PyPI Version](https://img.shields.io/pypi/v/ftl-sdk.svg)](https://pypi.org/project/ftl-sdk/)
[![Python Versions](https://img.shields.io/pypi/pyversions/ftl-sdk.svg)](https://pypi.org/project/ftl-sdk/)
[![License](https://img.shields.io/pypi/l/ftl-sdk.svg)](https://github.com/fastertools/ftl-cli/blob/main/LICENSE)
[![GitHub Actions](https://github.com/fastertools/ftl-cli/workflows/Test%20Python%20SDK/badge.svg)](https://github.com/fastertools/ftl-cli/actions)

## Installation

### Latest Stable Version

```bash
pip install ftl-sdk
```

### Specific Version

```bash
pip install ftl-sdk==0.1.0
```

### Development Version

```bash
pip install git+https://github.com/fastertools/ftl-cli.git#subdirectory=sdk/python
```

### From TestPyPI (Pre-releases)

```bash
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ ftl-sdk
```

## Overview

This SDK provides:
- Decorator-based API for easy tool creation
- Automatic JSON Schema generation from type hints
- Support for both sync and async functions
- Automatic return value conversion to MCP format
- Zero-dependency implementation (only requires `spin-sdk`)
- Full compatibility with Spin WebAssembly components
- Seamless deployment to Fermyon Cloud

## Requirements

- Python 3.10 or later
- `componentize-py` for building WebAssembly components
- `spin-sdk` for Spin runtime integration

## Quick Start

### 1. Create a new Python tool

```python
from ftl_sdk import FTL

# Create FTL application instance
ftl = FTL()

@ftl.tool
def echo(message: str) -> str:
    """Echo back the input."""
    return f"Echo: {message}"

# Create the Spin handler
Handler = ftl.create_handler()
```

### 3. Build and Deploy

```bash
# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install componentize-py spin-sdk ftl-sdk

# Build
ftl build

# Deploy to Fermyon Cloud
ftl deploy
```

## API Reference

### Decorator-based API

#### `FTL` Class

```python
ftl = FTL()
```

Creates an FTL application instance for registering tools.

#### `@ftl.tool` Decorator

```python
@ftl.tool
def my_tool(param: str) -> str:
    """Tool description."""
    return result

# With custom name and annotations
@ftl.tool(name="custom_name", annotations={"priority": "high"})
def another_tool(data: dict) -> dict:
    return {"processed": data}
```

The decorator:
- Automatically generates JSON Schema from type hints
- Extracts docstring as tool description
- Handles both sync and async functions
- Validates output against return type annotation

#### `ftl.create_handler()`

Creates a Spin HTTP handler that:
- Returns tool metadata on GET / requests
- Routes to specific tools on POST /{tool_name} requests
- Handles async/await for async tool functions
- Automatically converts return values to MCP format

### `ToolResponse` Helper Methods

```python
# Simple text response
ToolResponse.text("Hello, world!")

# Error response
ToolResponse.error("Something went wrong")

# Response with structured content
ToolResponse.with_structured("Operation complete", {"result": 42})
```

### `ToolContent` Helper Methods

```python
# Text content
ToolContent.text("Some text", {"priority": 0.8})

# Image content
ToolContent.image(base64_data, "image/png")

# Audio content
ToolContent.audio(base64_data, "audio/wav")

# Resource reference
ToolContent.resource({"uri": "file:///example.txt"})
```

### Type Guards

```python
# Check content types
if is_text_content(content):
    print(content["text"])
```

## Examples

### Basic Tools

```python
from ftl_sdk import FTL

ftl = FTL()

@ftl.tool
def echo(message: str) -> str:
    """Echo the input."""
    return f"Echo: {message}"

@ftl.tool
def reverse_text(text: str) -> str:
    """Reverse the input text."""
    return text[::-1]

@ftl.tool
def word_count(text: str) -> dict:
    """Count words in text."""
    count = len(text.split())
    return {"text": text, "word_count": count}

Handler = ftl.create_handler()
```

### Async Tools

```python
import asyncio
from ftl_sdk import FTL

ftl = FTL()

@ftl.tool
async def fetch_data(url: str) -> dict:
    """Fetch data from URL asynchronously."""
    # Simulate async HTTP request
    await asyncio.sleep(0.1)
    return {
        "url": url,
        "status": "success",
        "data": {"example": "data"}
    }

@ftl.tool
async def process_items(items: list[str]) -> dict:
    """Process items with async operations."""
    results = []
    for item in items:
        # Simulate async processing
        await asyncio.sleep(0.01)
        results.append(item.upper())
    
    return {
        "original": items,
        "processed": results,
        "count": len(results)
    }

# Mix sync and async tools
@ftl.tool
def sync_add(a: int, b: int) -> int:
    """Add two numbers synchronously."""
    return a + b

Handler = ftl.create_handler()
```

### Error Handling

```python
from ftl_sdk import FTL

ftl = FTL()

@ftl.tool
def divide(a: float, b: float) -> float:
    """Divide two numbers."""
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

# Async error handling
@ftl.tool
async def validate_data(data: dict) -> dict:
    """Validate data asynchronously."""
    if "required_field" not in data:
        raise KeyError("Missing required field: required_field")
    
    # Simulate async validation
    await asyncio.sleep(0.05)
    
    if not isinstance(data["required_field"], str):
        raise TypeError("required_field must be a string")
    
    return {"status": "valid", "data": data}

Handler = ftl.create_handler()
```

The FTL framework automatically catches exceptions and returns them as error responses.

## Development

### Setting Up Development Environment

1. **Clone the repository**:
   ```bash
   git clone https://github.com/fastertools/ftl-cli.git
   cd ftl-cli/sdk/python
   ```

2. **Create virtual environment**:
   ```bash
   python -m venv venv
   source venv/bin/activate  # On Windows: venv\Scripts\activate
   ```

3. **Install development dependencies**:
   ```bash
   make install-dev
   # or manually:
   pip install -e ".[dev]"
   pip install componentize-py
   ```

### Running Tests

```bash
# Run all tests
make test

# Run tests with coverage
make test-cov

# Run specific test
pytest tests/test_ftl_sdk.py::test_tool_response_text
```

### Code Quality

```bash
# Format code
make format

# Run linting
make lint

# Type checking
make type-check

# Run all quality checks
make quality
```

### Available Make Commands

```bash
make help         # Show all available commands
make install      # Install SDK
make install-dev  # Install with dev dependencies
make format       # Format code with black
make lint         # Run linting with ruff
make type-check   # Run type checking with mypy
make test         # Run tests
make test-cov     # Run tests with coverage
make clean        # Clean build artifacts
make build        # Build distribution packages
make publish      # Publish to PyPI
```

## Building to WebAssembly

Tools must be compiled to WebAssembly to run on Spin:

1. **Install dependencies**:
   ```bash
   pip install componentize-py spin-sdk ftl-sdk
   ```

2. **Build with componentize-py**:
   ```bash
   componentize-py -w spin-http componentize app -o app.wasm
   ```

3. **Or use FTL CLIs build command**:
   ```bash
   ftl build
   ```

## Best Practices

### Type Hints

Always use type hints for better code clarity and IDE support:

```python
from typing import Dict, Any
from ftl_sdk import ToolResponse

def my_handler(input_data: Dict[str, Any]) -> Dict[str, Any]:
    message: str = input_data.get("message", "")
    return ToolResponse.text(f"Received: {message}")
```

### Error Handling

Handle errors gracefully and return informative error messages:

```python
def safe_handler(input_data: Dict[str, Any]) -> Dict[str, Any]:
    try:
        # Validate required fields
        if "required_field" not in input_data:
            return ToolResponse.error("Missing required field: required_field")
        
        # Process input
        result = process_data(input_data["required_field"])
        return ToolResponse.text(f"Success: {result}")
        
    except ValueError as e:
        return ToolResponse.error(f"Invalid value: {e}")
    except Exception as e:
        return ToolResponse.error(f"Unexpected error: {e}")
```

### Testing Your Tools

Write comprehensive tests for your tools:

```python
import pytest
from your_module import your_handler

def test_handler_success():
    result = your_handler({"message": "test"})
    assert result["content"][0]["text"] == "Expected output"

def test_handler_missing_field():
    result = your_handler({})
    assert result.get("isError") is True
    assert "Missing required field" in result["content"][0]["text"]
```

## Important Notes

1. **Python Version**: Requires Python 3.10 or later. Python 3.11+ recommended.

2. **Zero Dependencies**: This SDK has no external dependencies beyond `spin-sdk`, keeping the WASM bundle size minimal.

3. **Input Validation**: The FTL gateway handles input validation against your JSON Schema. Your handler can assume inputs are valid.

4. **Virtual Environments**: Always use a virtual environment to ensure consistent builds.

5. **WASM Size**: Python WASM components are larger than TypeScript/Rust equivalents (~37MB), but this is acceptable for cloud deployment.

6. **Type Safety**: Use type hints and mypy for better code quality and fewer runtime errors.

7. **Code Quality**: The SDK includes development tools (black, ruff, mypy, pytest) to maintain high code quality standards.

## Deployment

Deploy to FTL:

```bash
# Deploy with auto-generated name
ftl deploy
```

## Development

Contributions are welcome! Please feel free to submit a Pull Request.

### Setting Up Development Environment

```bash
# Clone the repository
git clone https://github.com/fastertools/ftl-cli.git
cd ftl-cli/sdk/python

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install development dependencies
pip install -e ".[dev]"
pip install tox
```

### Running Tests

```bash
# Run tests for all Python versions
tox

# Run tests for specific Python version
tox -e py311

# Run linting and type checking
tox -e lint,type

# Run tests with coverage
tox -e py311 -- --cov-report=html
```

### Code Quality

```bash
# Format code
black src tests

# Run linter
ruff check src tests

# Type checking
mypy src
```

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for a list of changes in each release.

## License

Apache-2.0 - see [LICENSE](../../LICENSE) for details.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "ftl-sdk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": "FTL CLI Contributors <ftl-cli@fastertools.com>",
    "keywords": "ftl, mcp, wasm, webassembly, spin, fermyon, model-context-protocol",
    "author": null,
    "author_email": "FTL CLI Contributors <ftl-cli@fastertools.com>",
    "download_url": "https://files.pythonhosted.org/packages/a9/38/de3cf931134c01d5dc4ff34890503faf2ad3d9c393a3fb82453dceca2f99/ftl_sdk-0.1.0.tar.gz",
    "platform": null,
    "description": "# ftl-sdk (Python)\n\nPython SDK for building Model Context Protocol (MCP) tools that compile to WebAssembly.\n\n[![PyPI Version](https://img.shields.io/pypi/v/ftl-sdk.svg)](https://pypi.org/project/ftl-sdk/)\n[![Python Versions](https://img.shields.io/pypi/pyversions/ftl-sdk.svg)](https://pypi.org/project/ftl-sdk/)\n[![License](https://img.shields.io/pypi/l/ftl-sdk.svg)](https://github.com/fastertools/ftl-cli/blob/main/LICENSE)\n[![GitHub Actions](https://github.com/fastertools/ftl-cli/workflows/Test%20Python%20SDK/badge.svg)](https://github.com/fastertools/ftl-cli/actions)\n\n## Installation\n\n### Latest Stable Version\n\n```bash\npip install ftl-sdk\n```\n\n### Specific Version\n\n```bash\npip install ftl-sdk==0.1.0\n```\n\n### Development Version\n\n```bash\npip install git+https://github.com/fastertools/ftl-cli.git#subdirectory=sdk/python\n```\n\n### From TestPyPI (Pre-releases)\n\n```bash\npip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ ftl-sdk\n```\n\n## Overview\n\nThis SDK provides:\n- Decorator-based API for easy tool creation\n- Automatic JSON Schema generation from type hints\n- Support for both sync and async functions\n- Automatic return value conversion to MCP format\n- Zero-dependency implementation (only requires `spin-sdk`)\n- Full compatibility with Spin WebAssembly components\n- Seamless deployment to Fermyon Cloud\n\n## Requirements\n\n- Python 3.10 or later\n- `componentize-py` for building WebAssembly components\n- `spin-sdk` for Spin runtime integration\n\n## Quick Start\n\n### 1. Create a new Python tool\n\n```python\nfrom ftl_sdk import FTL\n\n# Create FTL application instance\nftl = FTL()\n\n@ftl.tool\ndef echo(message: str) -> str:\n    \"\"\"Echo back the input.\"\"\"\n    return f\"Echo: {message}\"\n\n# Create the Spin handler\nHandler = ftl.create_handler()\n```\n\n### 3. Build and Deploy\n\n```bash\n# Create virtual environment\npython3 -m venv venv\nsource venv/bin/activate\n\n# Install dependencies\npip install componentize-py spin-sdk ftl-sdk\n\n# Build\nftl build\n\n# Deploy to Fermyon Cloud\nftl deploy\n```\n\n## API Reference\n\n### Decorator-based API\n\n#### `FTL` Class\n\n```python\nftl = FTL()\n```\n\nCreates an FTL application instance for registering tools.\n\n#### `@ftl.tool` Decorator\n\n```python\n@ftl.tool\ndef my_tool(param: str) -> str:\n    \"\"\"Tool description.\"\"\"\n    return result\n\n# With custom name and annotations\n@ftl.tool(name=\"custom_name\", annotations={\"priority\": \"high\"})\ndef another_tool(data: dict) -> dict:\n    return {\"processed\": data}\n```\n\nThe decorator:\n- Automatically generates JSON Schema from type hints\n- Extracts docstring as tool description\n- Handles both sync and async functions\n- Validates output against return type annotation\n\n#### `ftl.create_handler()`\n\nCreates a Spin HTTP handler that:\n- Returns tool metadata on GET / requests\n- Routes to specific tools on POST /{tool_name} requests\n- Handles async/await for async tool functions\n- Automatically converts return values to MCP format\n\n### `ToolResponse` Helper Methods\n\n```python\n# Simple text response\nToolResponse.text(\"Hello, world!\")\n\n# Error response\nToolResponse.error(\"Something went wrong\")\n\n# Response with structured content\nToolResponse.with_structured(\"Operation complete\", {\"result\": 42})\n```\n\n### `ToolContent` Helper Methods\n\n```python\n# Text content\nToolContent.text(\"Some text\", {\"priority\": 0.8})\n\n# Image content\nToolContent.image(base64_data, \"image/png\")\n\n# Audio content\nToolContent.audio(base64_data, \"audio/wav\")\n\n# Resource reference\nToolContent.resource({\"uri\": \"file:///example.txt\"})\n```\n\n### Type Guards\n\n```python\n# Check content types\nif is_text_content(content):\n    print(content[\"text\"])\n```\n\n## Examples\n\n### Basic Tools\n\n```python\nfrom ftl_sdk import FTL\n\nftl = FTL()\n\n@ftl.tool\ndef echo(message: str) -> str:\n    \"\"\"Echo the input.\"\"\"\n    return f\"Echo: {message}\"\n\n@ftl.tool\ndef reverse_text(text: str) -> str:\n    \"\"\"Reverse the input text.\"\"\"\n    return text[::-1]\n\n@ftl.tool\ndef word_count(text: str) -> dict:\n    \"\"\"Count words in text.\"\"\"\n    count = len(text.split())\n    return {\"text\": text, \"word_count\": count}\n\nHandler = ftl.create_handler()\n```\n\n### Async Tools\n\n```python\nimport asyncio\nfrom ftl_sdk import FTL\n\nftl = FTL()\n\n@ftl.tool\nasync def fetch_data(url: str) -> dict:\n    \"\"\"Fetch data from URL asynchronously.\"\"\"\n    # Simulate async HTTP request\n    await asyncio.sleep(0.1)\n    return {\n        \"url\": url,\n        \"status\": \"success\",\n        \"data\": {\"example\": \"data\"}\n    }\n\n@ftl.tool\nasync def process_items(items: list[str]) -> dict:\n    \"\"\"Process items with async operations.\"\"\"\n    results = []\n    for item in items:\n        # Simulate async processing\n        await asyncio.sleep(0.01)\n        results.append(item.upper())\n    \n    return {\n        \"original\": items,\n        \"processed\": results,\n        \"count\": len(results)\n    }\n\n# Mix sync and async tools\n@ftl.tool\ndef sync_add(a: int, b: int) -> int:\n    \"\"\"Add two numbers synchronously.\"\"\"\n    return a + b\n\nHandler = ftl.create_handler()\n```\n\n### Error Handling\n\n```python\nfrom ftl_sdk import FTL\n\nftl = FTL()\n\n@ftl.tool\ndef divide(a: float, b: float) -> float:\n    \"\"\"Divide two numbers.\"\"\"\n    if b == 0:\n        raise ValueError(\"Cannot divide by zero\")\n    return a / b\n\n# Async error handling\n@ftl.tool\nasync def validate_data(data: dict) -> dict:\n    \"\"\"Validate data asynchronously.\"\"\"\n    if \"required_field\" not in data:\n        raise KeyError(\"Missing required field: required_field\")\n    \n    # Simulate async validation\n    await asyncio.sleep(0.05)\n    \n    if not isinstance(data[\"required_field\"], str):\n        raise TypeError(\"required_field must be a string\")\n    \n    return {\"status\": \"valid\", \"data\": data}\n\nHandler = ftl.create_handler()\n```\n\nThe FTL framework automatically catches exceptions and returns them as error responses.\n\n## Development\n\n### Setting Up Development Environment\n\n1. **Clone the repository**:\n   ```bash\n   git clone https://github.com/fastertools/ftl-cli.git\n   cd ftl-cli/sdk/python\n   ```\n\n2. **Create virtual environment**:\n   ```bash\n   python -m venv venv\n   source venv/bin/activate  # On Windows: venv\\Scripts\\activate\n   ```\n\n3. **Install development dependencies**:\n   ```bash\n   make install-dev\n   # or manually:\n   pip install -e \".[dev]\"\n   pip install componentize-py\n   ```\n\n### Running Tests\n\n```bash\n# Run all tests\nmake test\n\n# Run tests with coverage\nmake test-cov\n\n# Run specific test\npytest tests/test_ftl_sdk.py::test_tool_response_text\n```\n\n### Code Quality\n\n```bash\n# Format code\nmake format\n\n# Run linting\nmake lint\n\n# Type checking\nmake type-check\n\n# Run all quality checks\nmake quality\n```\n\n### Available Make Commands\n\n```bash\nmake help         # Show all available commands\nmake install      # Install SDK\nmake install-dev  # Install with dev dependencies\nmake format       # Format code with black\nmake lint         # Run linting with ruff\nmake type-check   # Run type checking with mypy\nmake test         # Run tests\nmake test-cov     # Run tests with coverage\nmake clean        # Clean build artifacts\nmake build        # Build distribution packages\nmake publish      # Publish to PyPI\n```\n\n## Building to WebAssembly\n\nTools must be compiled to WebAssembly to run on Spin:\n\n1. **Install dependencies**:\n   ```bash\n   pip install componentize-py spin-sdk ftl-sdk\n   ```\n\n2. **Build with componentize-py**:\n   ```bash\n   componentize-py -w spin-http componentize app -o app.wasm\n   ```\n\n3. **Or use FTL CLIs build command**:\n   ```bash\n   ftl build\n   ```\n\n## Best Practices\n\n### Type Hints\n\nAlways use type hints for better code clarity and IDE support:\n\n```python\nfrom typing import Dict, Any\nfrom ftl_sdk import ToolResponse\n\ndef my_handler(input_data: Dict[str, Any]) -> Dict[str, Any]:\n    message: str = input_data.get(\"message\", \"\")\n    return ToolResponse.text(f\"Received: {message}\")\n```\n\n### Error Handling\n\nHandle errors gracefully and return informative error messages:\n\n```python\ndef safe_handler(input_data: Dict[str, Any]) -> Dict[str, Any]:\n    try:\n        # Validate required fields\n        if \"required_field\" not in input_data:\n            return ToolResponse.error(\"Missing required field: required_field\")\n        \n        # Process input\n        result = process_data(input_data[\"required_field\"])\n        return ToolResponse.text(f\"Success: {result}\")\n        \n    except ValueError as e:\n        return ToolResponse.error(f\"Invalid value: {e}\")\n    except Exception as e:\n        return ToolResponse.error(f\"Unexpected error: {e}\")\n```\n\n### Testing Your Tools\n\nWrite comprehensive tests for your tools:\n\n```python\nimport pytest\nfrom your_module import your_handler\n\ndef test_handler_success():\n    result = your_handler({\"message\": \"test\"})\n    assert result[\"content\"][0][\"text\"] == \"Expected output\"\n\ndef test_handler_missing_field():\n    result = your_handler({})\n    assert result.get(\"isError\") is True\n    assert \"Missing required field\" in result[\"content\"][0][\"text\"]\n```\n\n## Important Notes\n\n1. **Python Version**: Requires Python 3.10 or later. Python 3.11+ recommended.\n\n2. **Zero Dependencies**: This SDK has no external dependencies beyond `spin-sdk`, keeping the WASM bundle size minimal.\n\n3. **Input Validation**: The FTL gateway handles input validation against your JSON Schema. Your handler can assume inputs are valid.\n\n4. **Virtual Environments**: Always use a virtual environment to ensure consistent builds.\n\n5. **WASM Size**: Python WASM components are larger than TypeScript/Rust equivalents (~37MB), but this is acceptable for cloud deployment.\n\n6. **Type Safety**: Use type hints and mypy for better code quality and fewer runtime errors.\n\n7. **Code Quality**: The SDK includes development tools (black, ruff, mypy, pytest) to maintain high code quality standards.\n\n## Deployment\n\nDeploy to FTL:\n\n```bash\n# Deploy with auto-generated name\nftl deploy\n```\n\n## Development\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n### Setting Up Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/fastertools/ftl-cli.git\ncd ftl-cli/sdk/python\n\n# Create virtual environment\npython -m venv venv\nsource venv/bin/activate  # On Windows: venv\\Scripts\\activate\n\n# Install development dependencies\npip install -e \".[dev]\"\npip install tox\n```\n\n### Running Tests\n\n```bash\n# Run tests for all Python versions\ntox\n\n# Run tests for specific Python version\ntox -e py311\n\n# Run linting and type checking\ntox -e lint,type\n\n# Run tests with coverage\ntox -e py311 -- --cov-report=html\n```\n\n### Code Quality\n\n```bash\n# Format code\nblack src tests\n\n# Run linter\nruff check src tests\n\n# Type checking\nmypy src\n```\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for a list of changes in each release.\n\n## License\n\nApache-2.0 - see [LICENSE](../../LICENSE) for details.\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "Python SDK for building MCP tools that compile to WebAssembly",
    "version": "0.1.0",
    "project_urls": {
        "Documentation": "https://github.com/fastertools/ftl-cli/tree/main/sdk/python",
        "Homepage": "https://github.com/fastertools/ftl-cli",
        "Issues": "https://github.com/fastertools/ftl-cli/issues",
        "Repository": "https://github.com/fastertools/ftl-cli"
    },
    "split_keywords": [
        "ftl",
        " mcp",
        " wasm",
        " webassembly",
        " spin",
        " fermyon",
        " model-context-protocol"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "73ffdd6383c48ab71f043b3084c03eab6d8d8086183f59ea32e0d440b50782d8",
                "md5": "30623a6745e1218ad3608c2023075e51",
                "sha256": "849d020e988542b17dc4007a83b3a491cc497d8b7b33ea0b0feeb97aff959670"
            },
            "downloads": -1,
            "filename": "ftl_sdk-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "30623a6745e1218ad3608c2023075e51",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 14242,
            "upload_time": "2025-08-04T03:54:27",
            "upload_time_iso_8601": "2025-08-04T03:54:27.994681Z",
            "url": "https://files.pythonhosted.org/packages/73/ff/dd6383c48ab71f043b3084c03eab6d8d8086183f59ea32e0d440b50782d8/ftl_sdk-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a938de3cf931134c01d5dc4ff34890503faf2ad3d9c393a3fb82453dceca2f99",
                "md5": "870d4d59e1951157d0202f472959f135",
                "sha256": "beec6090e1cf5940be808ef8552458a679a17beb692f783977adbbec59c799a4"
            },
            "downloads": -1,
            "filename": "ftl_sdk-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "870d4d59e1951157d0202f472959f135",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 21980,
            "upload_time": "2025-08-04T03:54:29",
            "upload_time_iso_8601": "2025-08-04T03:54:29.293918Z",
            "url": "https://files.pythonhosted.org/packages/a9/38/de3cf931134c01d5dc4ff34890503faf2ad3d9c393a3fb82453dceca2f99/ftl_sdk-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-04 03:54:29",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "fastertools",
    "github_project": "ftl-cli",
    "github_not_found": true,
    "lcname": "ftl-sdk"
}
        
Elapsed time: 1.61969s