Skip to content

json layer

github-actions[bot] edited this page Sep 17, 2026 · 4 revisions

🧾 JSON layer

Verdict: three independent JSON concerns. (1) JSON-RPC envelope — hand-rolled Jackson 3 streaming, raw-value passthrough. (2) User payloadsPayloadSerializer/Deserializer (Jackson default, kotlinx option). (3) Schemas/documents — library-neutral JsonDocument/JsonSchema in api, factories discovered by ServiceLoader keyed on source type.

✉️ JSON-RPC codec

JsonRpcCodec tachyon-core/src/main/java/dev/tachyonmcp/core/transport/jsonrpc/JsonRpcCodec.java:

📄 Documents & schemas (api)

Type Proof
JsonDocumentjson(), unwrap(Class), of(String) (no validation), parse, from(source, type) JsonDocument
JsonObject / JsonArray typed accessors (stringOpt, intOpt exact, …) JsonObject
JsonSchema (unchecked, generate(Class)) JsonSchema.java
JsonSchemaValidator + noop() JsonSchemaValidator
SPI JsonDocumentFactory<T> / JsonSchemaFactory<T> (sourceType, priority) json/spi/*.java

ServiceLoader registrations:

Services file Impls
core ...JsonDocumentFactory Jackson3JsonFactory(String), JacksonNodeJsonFactory, JacksonObjectJsonFactory
core ...JsonSchemaFactory above 3 + KtSchemaResourceFactory(Class, prio 0), JavaTypeSchemaFactory(Class, prio 1000), MapJsonFactory(Map)
kotlin KotlinxJsonElementFactory, KotlinxJsonObjectFactory
kt-schema KtSchemaReflectionFactory (Class, prio 10; declines on generator failure, e.g. Java record with int)

JsonSchema.generate(Class) chain = codegen resource → kt-schema reflection → Java reflection. JavaTypeSchemas covers records (required unless Optional/JSpecify @Nullable), POJOs (public getters/fields, only primitives required), enums, arrays/collections, maps (additionalProperties), java.time/UUID/URI formats; cycles ⇒ bare object. Factory declines non-object types so chain still fails for them JavaTypeSchemaFactory#priority.

Server requires exactly one String-source JsonSchemaFactory else ISE DefaultTachyonServer#discoverSchemaFactory; used to validate tool schema roots at registration JsonSchemaUtils#parseSchemaRoot.

KtSchemaResourceFactory looks up META-INF/kt-schema/schemas/<fqcn path>.json on context classloader (build-time generated) KtSchemaResourceFactory#sourceType.

✅ Validation

  • Default input and output validator NetworkntJsonSchemaValidator, dialect 2020-12, compiled-schema cache keyed by schema JSON string NetworkntJsonSchemaValidator.
  • Override via json { inputSchemaValidator / outputSchemaValidator / schemaValidator } JsonConfig. Output validator noop() skips output check ToolsCallHandler#validateOutput.
  • Registration rules (JsonSchemaUtils): input root must be type: object JsonSchemaUtils#validateInputSchemaRoot; output must be object JsonSchemaUtils#validateOutputSchemaRoot; x-mcp-header rules JsonSchemaUtilsprotocol-versions.

🔄 Payload serde

  • Default JacksonPayloadSerde over shared JsonUtils.mapper() (Duration deserialized from millis) JacksonPayloadSerde, JsonUtils#MAPPER.
  • ToolRequest.arguments() = Args (wraps JSON; decode(Class) via deserializer carried on request) tachyon-api/.../server/domain/Args.java.
  • Structured results serialized to JsonDocument before mapping JsonUtils.serializeStructured JsonDocument.
  • Kotlin: KxSerializationSerdetachyon-kotlin.

⚠️ Jackson 3 (tools.jackson.*): JsonNode.isString()/stringValue()/asString(), properties() — not Jackson 2 names.

Related: feature-registries, errors.


📄 source .llm-wiki/concepts/json-layer.md · updated 2026-09-17 · verified at 1a4081f4 · tags [concept, json, schema]

Clone this wiki locally