yoanm/jsonrpc-server-sdk
A framework-agnostic PHP SDK for building JSON-RPC 2.0 servers: define methods, dispatch requests and notifications to handlers, and return spec-compliant responses, with middleware and flexible configuration for integrating the protocol into your app.
Architecture fit. The SDK is deliberately transport-agnostic: its public surface is essentially handleRequest(string $jsonRpcRequest): string. That is a genuinely good architectural fit for Laravel, because it refuses to own HTTP. Laravel keeps routing, middleware, auth, rate limiting, and logging; the SDK owns only JSON-RPC 2.0 envelope handling (parse, dispatch, error-code shaping, batch/notification semantics). There is no framework lock-in and no global state to fight with Octane.
The trade-off is that the package ships as a library, not a framework integration. There is no service provider, no facade, no publishable config, no container-aware method resolution. The maintainer publishes a Symfony bundle (yoanm/jsonrpc-server-symfony-bundle) that supplies exactly this glue; for Laravel you rebuild roughly 100–200 lines of it yourself. That is the central TPM conclusion: low technical risk, but the integration work is yours and must be treated as owned code.
Integration feasibility. Feasible. A senior Laravel engineer can prove the happy path (two methods, success + error + batch) in a 1–2 day spike, and reach production hardening in one sprint. The concrete gaps to close:
invalid params responses; bridging to Laravel's Validator is manual.internal error objects, not Laravel 500 pages.Technical risk. Code risk is low: MIT, PSR-3 logging hooks, a narrow and well-tested domain, an actively maintained release (2025-12-13). Vendor risk is the real exposure: 5 stars, 0 dependents, a single maintainer, and effectively no community answer base. That is a bus-factor problem, not a correctness problem. Mitigate by isolating the SDK behind a thin internal adapter interface so a swap to sajya/server (the Laravel-native alternative) or a hand-rolled ~200-line dispatcher is a contained change rather than a rewrite.
Key questions.
symfony/* version constraints (options-resolver, config, validator) and do they resolve cleanly against Laravel 11/12's Symfony 7 set?id, no response) handled natively, and does batch preserve per-call error isolation?JsonRpcException with a numeric code?Stack fit. Laravel 10–12 on PHP 8.2+. The SDK's PSR-3 logger dependency binds cleanly to Laravel's Psr\Log\LoggerInterface; no queue, cache, or database coupling. It is stateless per request, which means it behaves identically under PHP-FPM and Octane, provided the server instance is built once and treated as immutable.
Migration path. Purely additive. Stand up a dedicated POST /rpc endpoint alongside existing REST routes — there is no reason to migrate existing consumers. Use namespaced method names (v1.user.get, v1.order.create) to get versioning for free, since JSON-RPC has no URL-based versioning. If replacing an existing RPC system, method names map 1:1 through the config registry, which makes a traffic-shadow cutover straightforward.
Compatibility. Several Laravel defaults actively work against JSON-RPC semantics and must be neutralized:
$request->getContent() (raw string), never $request->json() — the SDK wants the unparsed payload, and double-decoding breaks batch and notification handling.web group; use routes/api.php (or an explicit withoutMiddleware).application/json and application/json-rpc content types explicitly; Laravel's TrimStrings/ConvertEmptyStringsToNull middleware only touch input arrays, so the raw body is safe.config/jsonrpc.php) of method name → handler class, and bind it in a dedicated JsonRpcServiceProvider.Sequencing.
JsonRpcController (single action), JsonRpcMethodRegistry, JsonRpcServiceProvider, config/jsonrpc.php. Everything framework-facing lives here, nothing else in the app imports SDK classes directly.throttle middleware, per-method timeouts, structured request logging with method name and duration.Maintenance. Low churn expected, but the adapter layer is now your code and needs an owner. Pin to minor versions, enable automated dependency updates, and budget roughly 2–3 engineer-days per quarter for upgrades and Symfony/Laravel compatibility checks. The adapter boundary is the insurance policy: if the package stalls, replacement is a contained week, not a quarter.
Support. No commercial support, GitHub issues only, negligible community. Internal ownership is mandatory — there is no Stack Overflow safety net for edge cases. Compensate with above-average test coverage on the JSON-RPC envelope behaviors (batch, notification, parse error, invalid params), which are exactly the cases that will otherwise surface in production.
Scaling. Effectively free. Parsing and dispatch are microseconds of CPU; the endpoint is stateless and horizontally scales with the rest of the fleet. Two real considerations: batch amplification (one HTTP request → N method executions) needs an explicit cap and should be excluded from any "cheap" rate-limit tier; and per-method cost variance means a single expensive method can dominate capacity, so per-method metrics are required rather than aggregate endpoint latency.
Failure modes.
method not found, but the response shape must be validated so clients don't see a framework error page.internal error with no stack trace leakage, independent of APP_DEBUG.Ramp-up. One day for a senior Laravel engineer to be productive on the happy path; two to three days to internalize batch/notification semantics, the error-code contract, and the middleware interactions. Documentation is README-grade — accurate but example-light, with no Laravel-specific guidance. Given the tiny community, plan for a small internal design note (endpoint contract, method registry convention, error taxonomy) so the second engineer doesn't have to reverse-engineer the SDK.
How can I help you explore Laravel packages today?