Tachyon MCP is a Java 21+ and Kotlin Model Context Protocol (MCP) SDK built with Netty. It implements MCP 2025-11-25 and the upcoming MCP 2026-07-28 over Streamable HTTP and runs stateless by default. It passes all official conformance tests for both protocol versions!
π« Why Tachyon?
π§΅ Synchronous code, asynchronous runtime β write blocking handlers; Java virtual threads run them off the Netty event loop. No thread pools, reactive pipelines, or CompletableFuture boilerplate. Coroutine-first Kotlin DSL included.
π‘οΈ Stable APIs across spec changes β domain types (ToolHandler, ResourceHandler, PromptHandler, tasks) sit behind an internal protocol mapper. Spec upgrades change the mapper, not your handlers.
βοΈ Stateless by default β scale without session affinity on containers and serverless runtimes.
AWS Lambda needs an adapter that supports a listening HTTP server and long-lived SSE responses.
Opt into sessions for SSE resumability, Last-Event-ID replay, and TTL cleanup.
π Production transport β Netty with backpressure, graceful shutdown, DNS rebinding protection, and native transport auto-detection (io_uring β epoll β kqueue β NIO).
TL;DR
-
Add dependency:
<dependency> <groupId>dev.tachyonmcp</groupId> <artifactId>tachyon-core</artifactId> <version>1.0.0-beta.13</version> </dependency> -
Create MCP server:
import dev.tachyonmcp.server.TachyonServer; import dev.tachyonmcp.server.features.tools.ToolHandler; import dev.tachyonmcp.server.features.tools.ToolResult; public class WeatherMcpServer { public static void main(String... args) { var server = TachyonServer.builder() .name("weather-mcp") .withTools(tools -> tools.register(ToolHandler.of( b -> b.name("get_forecast") .description("Get weather forecast") .inputSchema(""" {"type":"object","properties":{"city":{"type":"string"}},"required":["city"]} """), (ctx, request) -> ToolResult.text("βοΈ 22Β°C")))) .port(8080) .build(); server.start(); } }
Documentation
| Guide | Description |
|---|---|
| Quickstart | Build a working server in 5 minutes |
| Configuration | Network, I/O engine (native transports), sessions, CORS |
| Tools | Sync/async handlers, input schema, ToolResult |
| Resources | Static URIs, dynamic handlers, URI templates |
| Tasks | Long-running operations, state machine, TasksExtension |
| Extensions | Custom protocol extensions, negotiation |
| FAQ | Java, frameworks, concurrency, deployment, and compatibility |
| Kotlin DSL | Coroutine-first DSL, TachyonServer { }, scope reference |
| Kotlin module | tachyon-kotlin module overview |
Agent Skill
Add agent skill to write better code using this SDK:
npx skills add kpavlov/tachyon --skill tachyon-mcp
The skill includes compilable Java and Kotlin example sources under .agents/skills/tachyon-mcp/resources/.
They are compiled as extra source roots of the e2e module during mvn test to keep them valid.
Check out Skills CLI for more options.
Features
Full MCP surface over Streamable HTTP, verified by the official conformance suites for 2025-11-25 and 2026-07-28:
The wire lifecycle varies by negotiated version; the detailed method list below describes the 2025-11-25 surface unless noted otherwise.
| Area | What you get |
|---|---|
| Tools | Sync & async handlers, JSON Schema 2020-12 input/output validation, outputSchema, annotations, per-tool taskSupport, list_changed |
| Resources | Static + dynamic handlers, URI templates, subscribe/unsubscribe with updated notifications, text & blob content |
| Prompts | List/get with resolver handlers, input-required (MRTR) flow, list_changed |
| Tasks | Full tasks/* lifecycle with enforced state machine, status broadcast, stale-task janitor, TasksExtension (SEP-1686) |
| Client calls | sampling/createMessage, elicitation (form and URL modes), client-initiated cancelled |
| Sessions | Stateless by default; opt-in SSE resumability, Last-Event-ID replay, TTL janitor, pluggable store/ID generator |
| Transport | Native transport auto-detect, backpressure watermarks, graceful drain-on-shutdown, CORS + origin/DNS-rebinding protection |
| Extensions | Negotiable protocol extensions (SEP-2133) with extension-gated tool visibility |
Core β JSON-RPC 2.0; Streamable HTTP (POST/GET-SSE/DELETE/OPTIONS); lifecycle initialize β initialized β ACTIVE; cursor pagination on all list methods; strict Accept validation (406); pending-request timeout.
Tools β tools/list (paginated), tools/call (isError), outputSchema + annotations, sync/async handlers, name validation (SEP-986), inline notifications/logging mid-call, JSON Schema 2020-12 validation (SEP-1613), notifications/tools/list_changed.
Resources β resources/list, resources/read (text & blob), resources/templates/list, subscribe/unsubscribe, list_changed + updated notifications, dynamic ResourceHandler.
Prompts β prompts/list (paginated), prompts/get, input-required flow, list_changed.
Tasks β tasks/list|get|cancel|result; state machine SUBMITTED β WORKING β INPUT_REQUIRED β COMPLETED/FAILED/CANCELLED (+ REJECTED/AUTH_REQUIRED); notifications/tasks/status on every transition; stale-task janitor; per-tool execution.taskSupport; TasksExtension (SEP-1686) exposing create_task + task://{id}, hidden from clients that don't negotiate it.
Logging & client calls β logging/setLevel per session, notifications/message above threshold, progress notifications; sampling/createMessage; elicitation form + URL modes; client-initiated notifications/cancelled.
Transport & sessions β Netty 4.2, io_uring/epoll/kqueue/NIO auto-detect, platform-thread event loops + virtual-thread handlers, writability backpressure, configurable idle timeouts; stateless or in-memory sessions, 5s janitor / 30s TTL, SSE disconnect survives (event-log replay on reconnect), graceful drain (shutdownGracePeriod, default 5s) before force-interrupt.
Quick Start
See docs/quickstart.md for a full walkthrough with Java and Kotlin examples, curl test, and next-step links.
TasksExtension (SEP-1686)
var server = TachyonServer.builder()
.extension(TasksExtension.instance()) // exposes create_task tool + task://{id} resource
.port(8080)
.build();
server.start();
MCP 2025-11-25 clients that include "extensions": {"io.modelcontextprotocol/tasks": {}} in their initialize capabilities receive the extension's tool and resource template. Clients that don't negotiate it see standard tasks/* methods. See docs/tasks.md.
Protocol isolation
Handler interfaces (ToolHandler, ResourceHandler, PromptHandler) and descriptor types use stable domain types. When Tachyon upgrades to a new protocol version, only the internal mapper layer changes; handler implementations are unaffected. Domain types track the 2026-07-28 spec shape where it improves on 2025-11-25 (e.g. Annotations.lastModified, ResourceLink in ContentBlock).
Performance
- Native transports β
io_uringβepollβkqueueβ NIO auto-detect - Write-buffer watermarks β 32 KB low / 128 KB high, backpressure wired end to end
- Batch flushing β
ctx.write()accumulates, onectx.flush()per boundary - Sharable handlers β
@Sharablepipeline handlers, no per-request allocation - Virtual threads β handlers offloaded from the event loop, no manual pools
- Streaming JSON-RPC β Jackson streaming codec, no or limited
ObjectMappertree round-trips
Not yet supported
- HTTP/2 β transport is HTTP/1.1
- Rate limiting
- Telemetry
License
Tachyon MCP is available under the terms of the Apache 2.0.
No comments yet
Be the first to share your take.