Files
Flash5/flash-extensions/flash-ext-mcp/docs/jackson-interop.md
T
Zakaria El OrcheandClaude Sonnet 5 d7f36a7aea
CI / Build & Test (push) Failing after 4m57s
feat(ext-mcp): add MCP (Model Context Protocol) server extension
Streamable HTTP transport (JSON-RPC 2.0 over POST), one-class-per-tool/resource/prompt
API mirroring RequestHandler, boot-time-precompiled schema/list payloads for a zero-alloc
hot path, and optional OAuth2 protection built on flash-ext-oidc (lazy-loaded, RFC 8707
audience binding, RFC 9728 Protected Resource Metadata). Registers the module in the
root and flash-extensions POMs and adds the ext-mcp commit scope to AGENTS.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 00:22:40 +00:00

3.4 KiB

Why no flash-ext-jackson interop (yet)

The decision

flash-ext-mcp does not depend on, or integrate with, flash-ext-jackson. It brings its own JSON handling (jackson-databind/jackson-core as a plain library dependency, wrapped by the internal McpJson utility) and never touches flash-ext-jackson's Json/JacksonMiddleware/ shared ObjectMapper, even if the host app has flash-ext-jackson installed. This was a deliberate choice, discussed and made explicitly — not an oversight — and is written down here so it isn't accidentally "fixed" later without re-litigating the trade-off.

Why

flash-ext-jackson's Json class is built around full databinding: mapper.readValue(bytes, SomeDto.class) / mapper.writeValueAsBytes(obj) — reflection-driven property matching in both directions. The MCP JSON-RPC envelope has a fixed, known shape ({jsonrpc, id, method, params} in, {jsonrpc, id, result|error} out) defined by a spec, not by application DTOs. Given that, hand-writing it with JsonGenerator directly is both simpler and strictly cheaper than round-tripping through databinding: no property-name matching, no reflection, no intermediate POJO graph for the parts of the response this extension controls (the envelope itself, tools/list/resources/list/prompts/list — precompiled once at boot, see tools-resources-prompts.md — and the fixed TextContent/TextResourceContents/ PromptMessage shapes). ToolArguments/PromptArguments read the incoming arguments object as a JsonNode tree, not as a databound class, for the same reason — a JSON-RPC tool call's arguments aren't a DTO with getters/setters, they're a dynamic, per-tool-defined bag of values.

This mirrors how flash-ext-oidc already handles its own internal JSON needs (json-smart for token-endpoint responses) independently of flash-ext-jackson — extensions with protocol-level JSON needs that are shaped by a spec, not by user code, own that JSON handling themselves rather than routing it through the app's general-purpose JSON extension.

What this means practically

  • Installing flash-ext-mcp never requires installing flash-ext-jackson. A pure MCP server with no other JSON REST routes has zero unrelated dependencies to configure.
  • If the host app does have flash-ext-jackson installed for its own REST routes, that ObjectMapper's configuration (custom modules, date formatting, naming strategy, etc.) is not consulted by flash-ext-mcp — the two JSON paths are entirely independent today.

What a future opt-in reuse could look like

Nothing here rules out a later, additive convenience layer: McpExtension.routes() could check ctx.find(ObjectMapper.class) (populated by JacksonExtension.provide()) and, if present, use that shared mapper as the backing for an escape hatch such as ToolArguments.as(Class<T>) or for a tool that wants to ToolResponse.success(someRecord) and have it serialized with the app's own conventions — falling back to a locally-constructed default ObjectMapper when flash-ext-jackson isn't installed, the same "prefer shared, degrade to sane default" shape already used for McpSecurity.AUTO. That would be purely additive on top of the JsonGenerator-based envelope/content writing described above, not a replacement for it — the fixed-shape protocol plumbing has no reason to ever go through databinding, regardless of what convenience layer gets added around it.