Skip to content

NextPDF Connect boot and discovery

Each transport has its own entry point and boot sequence. The transports share the registry, configuration, and gate as concepts. They run as independent processes, so starting one does not start the others.

Terminal window
composer require nextpdf/server

McpServer::create() wires the Model Context Protocol (MCP) server in a fixed order. First, it loads configuration, builds the security policy from that configuration, constructs the tool registry, and runs tier discovery. Next, it builds the in-memory document store from the configured time to live (TTL) and capacity, creates the stdio transport, and assembles the JSON-RPC protocol handler with the confirmation gate and audit logger. Then the server enters its read-handle-write loop and runs until standard input reaches end of file.

HttpServer::create() reads HttpConfig from the environment and applies command-line interface (CLI) overrides. It then resolves the application programming interface (API) key store in this preference order: the hot-reloading file store first, then the static file, then the environment. Next, it resolves the rate-limit and idempotency stores. They use Redis when Redis is configured and reachable, and fall back to in-memory storage otherwise. From there, the server opens the shared SQLite job store, builds the application services, and constructs the route table. Because the route table is built from detected tiers, it reflects the installed packages. RoadRunner then drives the worker request loop.

GrpcServer::create() resolves the same key store, builds the same application services, and registers the nextpdf.connect.v1 service with the Spiral gRPC worker. When the engine dependency is unavailable, the gRPC server still starts and serves health and capability queries. In that state, the process does not refuse to boot; instead, data-bearing remote procedure calls (RPCs) fail cleanly.

Discovery is the registry’s default registration step. The core tier registers first. Pro and Enterprise providers register next, if their classes resolve through class_exists(). The bundled Abstract Syntax Tree (AST) and mutation providers then register under the Pro tier, subject to their environment gates. Every registration is filtered through the enabled_tools security allowlist, and the MCP initialize response reports the resulting per-tier counts. See /connect/tool-catalog/.

No single configuration setting “enables transports.” Each transport is a separate entry point. REST and gRPC each have a separate RoadRunner profile. A deployment chooses transports by the profile it runs: .rr.yaml for REST, .rr.grpc.yaml for gRPC, or .rr.full.yaml for both. The transports run as independent processes. A missing MCP client never blocks the REST server, and a missing REST client never blocks MCP. See /connect/deployment/.

The MCP server resolves configuration in this precedence order: the environment (NEXTPDF_MCP_*) takes priority over the YAML file’s nextpdf_mcp section, which takes priority over built-in defaults. The REST and gRPC servers read HttpConfig from NEXTPDF_* environment variables with safe defaults. They do not read the MCP YAML file. See /connect/configuration/.

There is no dependency-injection container or service provider to register. Each create() factory constructs its own object graph explicitly and deterministically. Two injectable seams exist — the transport and the worker factory — and both are for testing, not for application wiring.

Inspect what discovery produced without serving traffic:

Terminal window
./vendor/bin/generate-skills --dry-run --list-tools

Boot the combined transports under one supervisor:

Terminal window
export NEXTPDF_API_KEYS_FILE=/run/secrets/api-keys
./vendor/bin/rr serve -c .rr.full.yaml
  • A missing tier does not fail boot. Tier discovery silently skips an absent Pro or Enterprise package. The server boots with the core catalog.

  • A downgrade override fails boot. A risk_level_overrides entry that weakens an approval_required tool throws during configuration load; the server refuses to start. This is intentional.

  • Redis failure degrades, it does not crash. If Redis is configured but unreachable at boot, the REST server falls back to in-memory stores. Verify Redis health rather than assuming Redis is in use.

Boot cost comes from parsing configuration, scanning the registry, and detecting tiers. The page performance_budget bounds this cost. The cost is paid once per process start, not per request.

The security policy is built before the registry, so the enabled_tools allowlist constrains discovery from the first registration. API keys are never read from the MCP YAML file; the networked transports resolve keys from a secret file or the environment. See /connect/security-and-operations/.

This page describes boot mechanics. The protocol and security citations are pinned on /transports/mcp/, /transports/rest/, /transports/grpc/, and /connect/security-and-operations/.

Tier detection at boot is the single point where nextpdf/premium contributes its Pro and Enterprise tools to the catalog, when nextpdf/premium is installed alongside the server.

  • /connect/tool-catalog/ — what discovery registers and why the count varies
  • /connect/configuration/ — the resolution order in detail
  • /connect/deployment/ — choosing transports via RoadRunner profiles
  • /transports/mcp/ · /transports/rest/ · /transports/grpc/ — per-transport detail