.Title

API Platform 4.3 - When Your API Meets AI

Cover photo by AffectionateSand8525source

# API Platform 4.3: When Your API Meets AI

I’m excited to announce API Platform 4.3! This release brings a game-changing feature: native support for the Model Context Protocol (MCP), letting your existing API resources be consumed by AI agents. Beyond MCP, we’ve shipped advanced filtering capabilities, security optimizations, better spec compliance, and a fresh docs UI.

Since 4.2, the community has been busy:

Thank you to everyone who contributed!

# MCP Component — Expose Your API to AI Agents

The headline feature of 4.3 is our new MCP (Model Context Protocol) component. MCP is an open standard that lets AI agents — think Claude, ChatGPT, or your own LLM-powered tools — discover and interact with APIs in a structured way. With API Platform, your existing resources can now be exposed as MCP tools and resources with minimal configuration.

The McpTool attribute turns any class into a callable tool that AI agents can invoke. Define an input schema via your class properties, point to a processor, and you’re done:

use ApiPlatform\Metadata\McpTool;

#[McpTool(
    name: 'process_message',
    description: 'Process a message with priority',
    processor: [McpToolAttribute::class, 'process']
)]
class McpToolAttribute
{
    public function __construct(
        private string $message,
        private int $priority = 1,
    ) {
    }

    public static function process($data): mixed
    {
        $data->setMessage('Processed: ' . $data->getMessage());
        $data->setPriority($data->getPriority() + 10);

        return $data;
    }
}

The class properties automatically generate the tool’s JSON Schema input. The AI agent sees a tool named process_message, knows it accepts a message string and an optional priority integer, and calls it directly.

The MCP component also supports collection tools (McpToolCollection), readable resources (McpResource), Laravel, SDK handler fallback, and structured content for richer agent interactions. Check out the full MCP documentation for more details.

# Scalar API Reference

Alongside Swagger UI and ReDoc, you can now use Scalar as your API documentation interface. Enable it with:

api_platform:
    enable_scalar: true

Then access it via the ?ui=scalar query parameter on your docs endpoint. Scalar provides a modern, polished UI for exploring your OpenAPI specification. It loads from CDN, so there’s no additional bundle to install.

# Advanced Filtering

API Platform 4.3 brings several major improvements to the filtering system.

# ComparisonFilter — Range Queries

The new ComparisonFilter is a decorator that wraps any existing filter (like ExactFilter or UuidFilter) and adds comparison operators: gt, gte, lt, lte, and ne.

use ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter;
use ApiPlatform\Doctrine\Orm\Filter\ExactFilter;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;

#[GetCollection(
    parameters: [
        'name' => new QueryParameter(filter: new ExactFilter()),
        'nameComparison' => new QueryParameter(
            filter: new ComparisonFilter(new ExactFilter()),
            property: 'name',
        ),
    ],
)]
class Product
{
    // ...
}

Usage: ?nameComparison[gte]=A&nameComparison[lt]=N — finally, range filtering without writing custom code.

# UuidFilter

A dedicated filter for UUID properties, composable with ComparisonFilter:

use ApiPlatform\Doctrine\Orm\Filter\ComparisonFilter;
use ApiPlatform\Doctrine\Orm\Filter\UuidFilter;
use ApiPlatform\Metadata\QueryParameter;
use Symfony\Component\Uid\Uuid;

#[GetCollection(
    parameters: [
        'id' => new QueryParameter(filter: new UuidFilter()),
        'idComparison' => new QueryParameter(
            filter: new ComparisonFilter(new UuidFilter()),
            property: 'id',
        ),
    ]
)]
class Device
{
    public Uuid $id;
}

# Filter Relations

IriFilter and UuidFilter now work on nested relations. Filter by a related entity’s property without any custom code:

use ApiPlatform\Doctrine\Orm\Filter\IriFilter;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;

#[GetCollection(
    parameters: [
        'publisher' => new QueryParameter(filter: new IriFilter()),
        'publisherCountry' => new QueryParameter(
            filter: new IriFilter(),
            property: 'publisher.country',
        ),
        'bookPublisher' => new QueryParameter(
            filter: new IriFilter(),
            property: 'books.publisher',
        ),
    ]
)]
class Author
{
    // ...relations to Publisher, Book, etc.
}

# ODM SortFilter

For MongoDB users, the new parameter-based SortFilter for ODM supports nested property sorting, bringing it in line with the ORM sort capabilities.

# Security: isGranted Before Provider

When a security expression doesn’t reference object, API Platform now evaluates it before calling the provider. This means the database query is skipped entirely for denied requests — better performance and no unnecessary work:

use ApiPlatform\Metadata\Get;

// Provider is NOT called if the user lacks ROLE_ADMIN
#[Get(
    uriTemplate: 'is_granted_test_call_provider/{id}',
    security: 'is_granted("ROLE_ADMIN")',
    provider: [self::class, 'provideShouldNotBeCalled']
)]
class IsGrantedTestResource
{
    public static function provideShouldNotBeCalled(): never
    {
        throw new \RuntimeException('provider should not get called');
    }
}

If your security expression references object or previous_object, the provider still runs first as expected. This optimization is automatic — no configuration needed.

# Standards & Specification Compliance

# LDP Headers

API Platform now automatically adds Accept-Post and Allow headers per the Linked Data Platform specification. Every response includes the allowed HTTP methods for that URI template, and POST endpoints advertise the accepted content types. This improves discoverability for hypermedia clients.

# ProblemExceptionInterface

Proper RFC 7807 Problem Detail field mapping is now supported via ProblemExceptionInterface. Map your exception properties directly to type, title, detail, status, and instance fields in the problem response.

# Hydra @id Consistency

The class @id in Hydra documentation now consistently uses #ShortName format. Semantic types are expressed via rdfs:subClassOf, making the Hydra vocabulary more consistent and interoperable.

# DX & Performance Improvements

# Upgrade

composer update api-platform/symfony:^4.3

or

composer update api-platform/laravel:^4.3

# Thanks

A huge thank you to all 60 contributors who made this release possible. Check out the full changelog for the complete list of changes.

If you enjoy API Platform, consider sponsoring the project!