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.ServerObject: The mainServerclass, 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 boundServerTransportInterfaceand coordinating interactions with theProcessorandClientStateManager.
- 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 theProtocolto 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
Registryattempts 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). Registrycache 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
ConfigurationRepositoryInterfaceRemoved: This interface and its default implementation (ArrayConfigurationRepository) have been removed.ConfigurationValue Object: A newPhpMcp\Server\Configurationreadonly 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 theProcessorto resolve user-defined handler classes and their dependencies. - Improved
BasicContainer: The default DI container (PhpMcp\Server\Defaults\BasicContainer) now supports simple constructor auto-wiring. ClientStateManagerDefault Cache: If noCacheInterfaceis provided to theClientStateManager, it now defaults to an in-memoryPhpMcp\Server\Defaults\ArrayCache.
Schema Generation and Validation
- Removed Optimistic String Format Inference: The
SchemaGeneratorno longer automatically infers JSON Schemaformatkeywords (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/callparameters 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\StdioServerTransportandPhpMcp\Server\Transports\HttpServerTransport, both implementingServerTransportInterface.StdioServerTransportconstructor now accepts custom input/output stream resources, improving testability and flexibility (defaults toSTDIN/STDOUT).HttpServerTransportconstructor now accepts an array of request interceptor callables for custom request pre-processing (e.g., authentication), and also takeshost,port,mcpPathPrefix, andsslContextfor server configuration.
- Windows
stdioLimitation:StdioServerTransportnow throws aTransportExceptionif instantiated with defaultSTDIN/STDOUTon Windows, due to PHP's limitations with non-blocking pipes, guiding users toWSLorHttpServerTransport. - Aware Interfaces: Transports can implement
LoggerAwareInterfaceandLoopAwareInterfaceto receive the configured Logger and Loop instances when$server->listen()is called. - Removed: The old
StdioTransportHandler,HttpTransportHandler, andReactPhpHttpTransportHandlerclasses.
Capabilities Configuration
Model\CapabilitiesClass: Introduced a newPhpMcp\Server\Model\Capabilitiesvalue object (created viaCapabilities::forServer(...)) to explicitly configure and represent server capabilities.
Exception Handling
McpServerException: Renamed the base exception fromMcpExceptiontoPhpMcp\Server\Exception\McpServerException.- New Exception Types: Added more specific exceptions:
ConfigurationException,DiscoveryException,DefinitionException,TransportException,ProtocolException.
Fixes
- Fixed
StdioServerTransportnot cleanly exiting onCtrl+Cdue to event loop handling. - Fixed
TypeErrorinJsonRpc\Responsefor parse errors withnullID. - Corrected discovery caching logic for explicit
discover()calls. - Improved
HttpServerTransportrobustness 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
LoggerAwareInterfaceandLoopAwareInterfacefor dependency injection into transports. - Refined internal event handling between transport implementations and the
Protocol. - Renamed
TransportStatetoClientStateManagerand introduced aClientStateValue Object.
Documentation and Examples
- Significantly revised
README.mdto reflect the new architecture, API, discovery flow, transport usage, and configuration. - Added new and updated examples for standalone
stdioandhttpservers, 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);
httpandreactphpoptions forrun()were already invalid and are fully removed.- Configuration (
ConfigurationRepositoryInterfaceRemoved): Configuration is now handled via theConfigurationVO 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
ServerBuilderusingwithLogger(),withCache(),withLoop()or rely on the builder's defaults.
- If using
- Transport Handlers Replaced:
StdioTransportHandler,HttpTransportHandler,ReactPhpHttpTransportHandlerare removed.- Use
new StdioServerTransport()ornew HttpServerTransport(...)and pass them to$server->listen(). - Constructor signatures and interaction patterns have changed.
RegistryCache Methods Renamed:saveElementsToCacheis nowsaveDiscoveredElementsToCache, andclearCacheis nowclearDiscoveredElements. Their behavior is also changed to only affect discovered elements.- Core Component Constructors: The constructors for
Registry,Processor,ClientStateManager(previouslyTransportState),Discoverer,DocBlockParserhave changed. Update any direct instantiations (though typically these are managed internally). - Exception Renaming:
McpExceptionis nowMcpServerException. Updatecatchblocks accordingly. - Default Null Logger: Logging is effectively disabled by default. Provide a logger via
ServerBuilder->withLogger()to enable it. - Schema Generation: Automatic string
formatinference (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