API Platform 4.3 - When Your API Meets AI
Cover photo by AffectionateSand8525 — source
# 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:
- 349 contributions merged
- 60 contributors
- 1,222 files changed, 43,485 insertions and 8,094 deletions
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
- Default Parameters —
new QueryParameter(default: 'foo')sets default values when a parameter isn’t provided genIdconfiguration —#[ApiProperty(genId: false)]or global config to control blank node ID generation- Cached operation metadata factory — PSR cache layer for operation lookups, reducing repeated metadata resolution
- OpenSearch support — the Elasticsearch component now works with OpenSearch
- PartialSearchFilter
caseSensitive—new PartialSearchFilter(true)for case-sensitive partial matching - Readonly entity — entities marked as readonly automatically have PUT/PATCH operations removed
- UUID/ULID parameter validation — query and header parameters with
uuidorulidformat are automatically validated - SkipAutoconfigure attribute — opt out of Laravel’s auto-discovery for specific resources
- JSON Schema — normalization/denormalization schemas can be controlled per attribute
# 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!