Server API¶
The Server class runs against a TransportInterface. It blocks the caller until the transport closes. Build one
with the fluent ServerBuilder, then run it against any transport implementation.
use Nexus\Mcp\Server\ServerBuilder;
use Nexus\Mcp\Server\Transport\StdioServerTransport;
$server = (new ServerBuilder())
->setServerInfo(name: 'my-server', version: '1.0.0')
// ... register features ...
->build()
;
$server->run(new StdioServerTransport());
Server::run() returns when the transport closes. For the stdio transport, that is EOF on stdin. A request-scoped
transport such as Streamable HTTP uses
Server::listen() instead. That method attaches the dispatcher and returns, so the HTTP host keeps driving the
loop.
Guide¶
- Server configuration: server info and its disclosure, instructions, the logger, and the in-flight dispatch cap.
- Tools: registering tools, structured content, and schema validation.
- Prompts: registering prompt renderers.
- Resources: static and templated resources, and the cache hints every read and list result carries.
- Completions: serving
completion/completefrom a completion store. - Stores and pagination: page size, custom store implementations, and runtime mutation.
- Custom handlers: vendor-extension methods and spec-method overrides.
- Extensions: enabling SEP-2133 extensions and the declared-capability gate on their methods.
- Tasks: the SEP-2663 tasks extension. It brokers tool calls into polled long-running tasks.
- Apps: the SEP-1865 MCP Apps extension. It declares
ui://view resources and links tools to them. - Capability advertisement: how
ServerCapabilitiesis derived from what you registered. - Subscriptions: serving
subscriptions/listenstreams and the list-changed notifications. - ServerContext: what every handler receives.
- Asking the client for input: the
InputRequiredResultflow and elicitation.
You can also declare tools, prompts, resources, completions, and the server identity with attributes. Mark a plain
object with #[AsTool], #[AsPrompt], #[AsResource], #[AsResourceTemplate], #[AsCompletion], or
#[AsServer], then register it in one call with ServerBuilder::register(). See
Attribute discovery for the full reference.
Lifecycle¶
Build¶
build() validates the configuration and returns a Server instance. For example, the server info must be set.
Run¶
run($transport) registers the listener chain on the transport and starts it. The call blocks until the transport
closes.
Dispatch¶
While the server runs, the dispatcher classifies each inbound envelope and routes it to its handler. The protocol
is stateless, so every request dispatches immediately. The dispatcher reads the client's identity and capabilities
from the request's _meta.
A request for an unregistered method gets a MethodNotFound error. A malformed envelope gets an InvalidRequest
or a ParseError error.
Shutdown¶
The transport signals shutdown when it closes. For stdio, that is EOF on stdin. The dispatcher drains the in-flight
coroutines before the transport's close listeners fire, so responses already in flight are flushed before the
process exits. On an event-loop HTTP host, call close() on the transport before stopping the HTTP server:
closing ends every open subscriptions/listen stream, and the HTTP server's own stop waits for those responses to
finish, so the reverse order deadlocks with a stream open.
See also¶
- Getting started: install and a minimal server.
- Attribute discovery: declaring features with attributes.
- Client API: the other side of the connection.
- Transports: stdio, Streamable HTTP, and the transport contract.
- Authorization: protecting a Streamable HTTP server with OAuth 2.1.
- Error handling: how failures surface on both sides.