Metadata-Version: 2.4
Name: cognite-function-apps
Version: 0.13.1
Summary: FastAPI-style framework for building composable Function Apps for Cognite Functions with automatic OpenAPI schema generation and MCP integration
Project-URL: Repository, https://github.com/cognitedata/cognite-function-apps
Project-URL: Changelog, https://github.com/cognitedata/cognite-function-apps/releases
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: cognite-sdk>=7.87.0
Requires-Dist: pydantic>=2.10.5
Requires-Dist: typing-extensions>=4.11.0
Provides-Extra: cli
Requires-Dist: typer>=0.9.0; extra == 'cli'
Requires-Dist: uvicorn>=0.37.0; extra == 'cli'
Provides-Extra: tracing
Requires-Dist: opentelemetry-api>=1.20.0; extra == 'tracing'
Requires-Dist: opentelemetry-exporter-otlp>=1.20.0; extra == 'tracing'
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'tracing'
Description-Content-Type: text/markdown

# Function Apps

A framework for building structured, self-describing APIs on Cognite Functions — with type-safe routing, automatic validation, and native AI agent support.

## Why Function Apps?

**1. Classic functions are black boxes**

A standard Cognite Function exposes a single `handle(client, data)` endpoint with no machine-readable description of what operations it supports, what inputs they accept, or what they return. You have to read the source to understand it — and AI agents simply can't call it without custom tooling.

Function Apps are self-describing. Built-in `/schema`, `/routes`, and `/health` endpoints let any caller — human or AI agent — discover what a function provides and how to invoke it. This is the foundation for native MCP support and the interactive local dev server.

**2. The 100-function limit**

CDF projects start with a limit of 100 Cognite Functions (extendable to 250 on request). Many customers have collections of 3–10 tightly related functions that logically belong together. Function Apps lets you package those into a single deployable unit with proper internal routing, so you stop burning one slot per operation.

**3. Dynamic workflow orchestration**

Complex use cases — like [equipment monitoring](https://docs.google.com/presentation/d/15iDP5RSFkdjQ_Niq4IQEZQUWdryeLXkWag7XgEiw9bc/edit#slide=id.g3a2a8ddaba9_0_0) — require functions that coordinate and chain operations dynamically. The composable app architecture makes this tractable.

**4. Observability and better habits**

Customers hitting runtime limits often can't tell whether they're CPU-bound or I/O-bound. Built-in tracing and enforced type annotations make it possible to actually diagnose that, and nudge toward code that's easier to maintain and hand off.

**The boilerplate problem** is also real. Standard [Cognite Functions](https://docs.cognite.com/cdf/functions/) require a bare `handle(client, data)` function that becomes unwieldy for complex APIs:

```python
def handle(client, data):
    try:
        asset_no = int(data["assetNo"])  # Manual validation
        include_tax = data.get("includeTax", "false").lower() == "true"  # Manual parsing
        # Handle routing manually based on data
        if data.get("action") == "get_item":
            # Implementation here
        elif data.get("action") == "create_item":
            # Different implementation
    except Exception as e:
        return {"error": str(e)}  # Basic error handling
```

**With Function Apps:**

```python
@app.get("/items/{item_id}")
def get_item(client: CogniteClient, item_id: int, include_tax: bool = False) -> ItemResponse:
    """Retrieve an item by ID."""
    item = Item(name=f"Item {item_id}", price=100.0, tax=10.0 if include_tax else None)
    return ItemResponse(id=item_id, item=item, total_price=item.price + (item.tax or 0))
```

## Key Features

- **Type-safe routing** - Decorator-based syntax with automatic validation
- **Async/await support** - Write both sync and async handlers
- **Error handling** - Comprehensive error handling with structured responses
- **Logging** - Enterprise logging with dependency injection
- **Distributed tracing** - OpenTelemetry-based tracing
- **Dependency injection** - Inject custom dependencies
- **Introspection** - Built-in schema, routes, health endpoints
- **Model Context Protocol** - Native AI tool exposure
- **Local development server** - Test locally with interactive API docs
- **Function client** - Notebook-first client for exploring functions

## Installation

**Requirements:**

- Python 3.10 or higher
- uv (recommended) or pip

```bash
# Install the package
pip install cognite-function-apps

# Optional: Install with CLI support for dev server
pip install cognite-function-apps[cli]

# Optional: Install with tracing support
pip install cognite-function-apps[tracing]
```

## Quick Start

```python
from cognite.client import CogniteClient
from pydantic import BaseModel
from cognite_function_apps import FunctionApp, create_function_service

# Create your app
app = FunctionApp(title="My API", version="1.0.0")

# Define your models
class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

class ItemResponse(BaseModel):
    id: int
    item: Item
    total_price: float

# Define your endpoints
@app.get("/items/{item_id}")
def get_item(
    client: CogniteClient,
    item_id: int,
    include_tax: bool = False
) -> ItemResponse:
    """Retrieve an item by ID"""
    item = Item(
        name=f"Item {item_id}",
        price=100.0,
        tax=10.0 if include_tax else None
    )
    total = item.price + (item.tax or 0)
    return ItemResponse(id=item_id, item=item, total_price=total)

@app.post("/items/")
def create_item(client: CogniteClient, item: Item) -> ItemResponse:
    """Create a new item"""
    new_id = 12345  # Your creation logic here
    total = item.price + (item.tax or 0)
    return ItemResponse(id=new_id, item=item, total_price=total)

# Wraps the app in the handle(client, data) interface expected by Cognite Functions
handle = create_function_service(app)
```

## Test Locally

Install with CLI support and run the development server:

```bash
pip install cognite-function-apps[cli]
fun serve examples/
```

Visit `http://localhost:8000/docs` for interactive API documentation.

## Examples

The framework includes a complete example in `examples/handler.py` demonstrating:

- Type-safe routing with decorator syntax
- MCP integration for AI tool exposure
- Built-in introspection endpoints
- Async handler support
- Composable app architecture

## License

This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.

## Acknowledgments

- Built specifically for [Cognite Data Fusion](https://www.cognite.com/) [Functions](https://docs.cognite.com/cdf/functions/) platform
- Decorator routing syntax inspired by [FastAPI](https://fastapi.tiangolo.com/)
- Data validation powered by [Pydantic](https://pydantic-docs.helpmanual.io/)
