PHP MCP Server v2.0.0
This release marks a significant architectural refactoring of the package, aimed at improving modularity, testability, flexibility, and aligning its structure more closely with the php-mcp/client
library. The core functionality remains, but the way servers are configured, run, and integrated has fundamentally changed.
What's Changed
Core Architecture Overhaul
- Decoupled Design: The server core logic is now separated from the transport (network/IO) layer.
ServerBuilder
: A new fluent builder (Server::make()
) is the primary way to configure server identity, dependencies (Logger, Cache, Container, Loop), capabilities, and manually registered elements.Server
Object: The mainServer
class, created by the builder, now holds the configured core components (Registry
,Processor
,ClientStateManager
,Configuration
) but is transport-agnostic itself.ServerTransportInterface
: A new event-driven interface defines the contract for server-side transports (Stdio, Http). Transports are now responsible solely for listening and raw data transfer, emitting events for lifecycle and messages.Protocol
: A new internal class acts as a bridge, listening to events from a boundServerTransportInterface
and coordinating interactions with theProcessor
andClientStateManager
.
- Explicit Server Execution:
- The old
$server->run(?string)
method is removed. $server->listen(ServerTransportInterface $transport)
: Introduced as the primary way to start a standalone server. It binds theProtocol
to the provided transport, starts the listener, and runs the event loop (making it a blocking call).
- The old
Discovery and Caching Refinements
- Explicit Discovery: Attribute discovery is no longer triggered automatically during
build()
. You must now explicitly call$server->discover(basePath: ..., scanDirs: ...)
after building the server instance if you want to find elements via attributes. - Caching Behavior:
- Only discovered elements are eligible for caching. Manually registered elements (via
ServerBuilder->with*
methods) are never cached. - The
Registry
attempts to load discovered elements from cache upon instantiation (duringServerBuilder::build()
). - Calling
$server->discover()
will first clear any previously discovered/cached elements from the registry before scanning. It then saves the newly discovered results to the cache if enabled (saveToCache: true
). Registry
cache methods renamed for clarity:saveDiscoveredElementsToCache()
andclearDiscoveredElements()
.Registry::isLoaded()
renamed todiscoveryRanOrCached()
for better clarity.
- Only discovered elements are eligible for caching. Manually registered elements (via
- Manual vs. Discovered Precedence: If an element is registered both manually and found via discovery/cache with the same identifier (name/URI), the manually registered version always takes precedence.
Dependency Injection and Configuration
ConfigurationRepositoryInterface
Removed: This interface and its default implementation (ArrayConfigurationRepository
) have been removed.Configuration
Value Object: A newPhpMcp\Server\Configuration
readonly value object bundles core dependencies (Logger, Loop, Cache, Container, Server Info, Capabilities, TTLs) assembled by theServerBuilder
.- Simplified Dependencies: Core components (
Registry
,Processor
,ClientStateManager
,DocBlockParser
,Discoverer
) now have simpler constructors, accepting direct dependencies. - PSR-11 Container Role: The container provided via
ServerBuilder->withContainer()
(or the defaultBasicContainer
) is now primarily used by theProcessor
to resolve user-defined handler classes and their dependencies. - Improved
BasicContainer
: The default DI container (PhpMcp\Server\Defaults\BasicContainer
) now supports simple constructor auto-wiring. ClientStateManager
Default Cache: If noCacheInterface
is provided to theClientStateManager
, it now defaults to an in-memoryPhpMcp\Server\Defaults\ArrayCache
.
Schema Generation and Validation
- Removed Optimistic String Format Inference: The
SchemaGenerator
no longer automatically infers JSON Schemaformat
keywords (like "date-time", "email") for string parameters. This makes default schemas less strict, avoiding validation issues for users with simpler string formats. Specific format validation should now be handled within tool/resource methods or via future explicit schema annotation features. - Improved Tool Call Validation Error Messages: When
tools/call
parameters fail schema validation, the JSON-RPC error response now includes a more informative summary message detailing the specific validation failures, in addition to the structured error data.
Transports
- New Implementations: Introduced
PhpMcp\Server\Transports\StdioServerTransport
andPhpMcp\Server\Transports\HttpServerTransport
, both implementingServerTransportInterface
.StdioServerTransport
constructor now accepts custom input/output stream resources, improving testability and flexibility (defaults toSTDIN
/STDOUT
).HttpServerTransport
constructor now accepts an array of request interceptor callables for custom request pre-processing (e.g., authentication), and also takeshost
,port
,mcpPathPrefix
, andsslContext
for server configuration.
- Windows
stdio
Limitation:StdioServerTransport
now throws aTransportException
if instantiated with defaultSTDIN
/STDOUT
on Windows, due to PHP's limitations with non-blocking pipes, guiding users toWSL
orHttpServerTransport
. - Aware Interfaces: Transports can implement
LoggerAwareInterface
andLoopAwareInterface
to receive the configured Logger and Loop instances when$server->listen()
is called. - Removed: The old
StdioTransportHandler
,HttpTransportHandler
, andReactPhpHttpTransportHandler
classes.
Capabilities Configuration
Model\Capabilities
Class: Introduced a newPhpMcp\Server\Model\Capabilities
value object (created viaCapabilities::forServer(...)
) to explicitly configure and represent server capabilities.
Exception Handling
McpServerException
: Renamed the base exception fromMcpException
toPhpMcp\Server\Exception\McpServerException
.- New Exception Types: Added more specific exceptions:
ConfigurationException
,DiscoveryException
,DefinitionException
,TransportException
,ProtocolException
.
Fixes
- Fixed
StdioServerTransport
not cleanly exiting onCtrl+C
due to event loop handling. - Fixed
TypeError
inJsonRpc\Response
for parse errors withnull
ID. - Corrected discovery caching logic for explicit
discover()
calls. - Improved
HttpServerTransport
robustness for initial SSE event delivery and POST body handling. - Ensured manual registrations correctly take precedence over discovered/cached elements with the same identifier.
Internal Changes
- Introduced
LoggerAwareInterface
andLoopAwareInterface
for dependency injection into transports. - Refined internal event handling between transport implementations and the
Protocol
. - Renamed
TransportState
toClientStateManager
and introduced aClientState
Value Object.
Documentation and Examples
- Significantly revised
README.md
to reflect the new architecture, API, discovery flow, transport usage, and configuration. - Added new and updated examples for standalone
stdio
andhttp
servers, demonstrating discovery, manual registration, custom dependency injection, complex schemas, and environment variable usage.
Breaking Changes
This is a major refactoring with significant breaking changes:
Server->run()
Method Removed: Replace calls to$server->run('stdio')
with:The$transport = new StdioServerTransport(); // Optionally call $server->discover(...) first $server->listen($transport);
http
andreactphp
options forrun()
were already invalid and are fully removed.- Configuration (
ConfigurationRepositoryInterface
Removed): Configuration is now handled via theConfiguration
VO assembled byServerBuilder
. Remove any usage of the oldConfigurationRepositoryInterface
. Core settings like server name/version are set viawithServerInfo
, capabilities viawithCapabilities
. - Dependency Injection:
- If using
ServerBuilder->withContainer()
with a custom PSR-11 container, that container is now only responsible for resolving your application's handler classes and their dependencies. - Core server dependencies (Logger, Cache, Loop) must be provided explicitly to the
ServerBuilder
usingwithLogger()
,withCache()
,withLoop()
or rely on the builder's defaults.
- If using
- Transport Handlers Replaced:
StdioTransportHandler
,HttpTransportHandler
,ReactPhpHttpTransportHandler
are removed.- Use
new StdioServerTransport()
ornew HttpServerTransport(...)
and pass them to$server->listen()
. - Constructor signatures and interaction patterns have changed.
Registry
Cache Methods Renamed:saveElementsToCache
is nowsaveDiscoveredElementsToCache
, andclearCache
is nowclearDiscoveredElements
. Their behavior is also changed to only affect discovered elements.- Core Component Constructors: The constructors for
Registry
,Processor
,ClientStateManager
(previouslyTransportState
),Discoverer
,DocBlockParser
have changed. Update any direct instantiations (though typically these are managed internally). - Exception Renaming:
McpException
is nowMcpServerException
. Updatecatch
blocks accordingly. - Default Null Logger: Logging is effectively disabled by default. Provide a logger via
ServerBuilder->withLogger()
to enable it. - Schema Generation: Automatic string
format
inference (e.g., "date-time") removed fromSchemaGenerator
. String parameters are now plain strings in the schema unless a more advanced format definition mechanism is used in the future.
Deprecations
- (None introduced in this refactoring, as major breaking changes were made directly).
Full Changelog: 1.1.0...2.0.0