tachyon

mcp
Security Audit
Warn
Health Warn
  • License รขโ‚ฌโ€ License: Apache-2.0
  • Description รขโ‚ฌโ€ Repository has a description
  • Active repo รขโ‚ฌโ€ Last push 0 days ago
  • Low visibility รขโ‚ฌโ€ Only 5 GitHub stars
Code Pass
  • Code scan รขโ‚ฌโ€ Scanned 6 files during light audit, no dangerous patterns found
Permissions Pass
  • Permissions รขโ‚ฌโ€ No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

๐Ÿ’ซ Modern MCP Runtime for JVM

README.md

Maven Central
Build
Conformance 46 of 46
Ask DeepWiki

Tachyon MCP โ€” A Java 25 Model Context Protocol (MCP) server built on Netty 4.2.
Fully implements MCP spec 2025-11-25 Streamable HTTP transport, session lifecycle, native I/O transports, and a stateless mode for serverless deployments.

TL;DR

import dev.tachyonmcp.server.TachyonMcpServer;
import dev.tachyonmcp.server.features.tools.AbstractSyncToolHandler;
import dev.tachyonmcp.server.features.tools.ToolDescriptor;
import dev.tachyonmcp.server.features.tools.ToolResult;
import dev.tachyonmcp.server.session.McpContext;
import tools.jackson.databind.node.JsonNodeFactory;

void main() {
    var schema = JsonNodeFactory.instance.objectNode();
    schema.put("type", "object");
    schema.putObject("properties").putObject("city").put("type", "string");

    TachyonMcpServer.builder()
        .name("weather-mcp")
        .tool(new AbstractSyncToolHandler(
            ToolDescriptor.builder("get_forecast")
                .description("Get weather forecast")
                .inputSchema(schema)
                .build()) {
            @Override
            public Object handle(McpContext ctx, Object args) {
                return ToolResult.text("โ˜€๏ธ 22ยฐC");
            }
        })
        .stateless(true)
        .port(8080)
        .bind();
}

Features

โœ… Core Protocol (46/46 conformance tests passing)

  • JSON-RPC 2.0 โ€” request/response/error/notification
  • Streamable HTTP โ€” POST, GET (SSE), DELETE, OPTIONS
  • Lifecycle โ€” initialize โ†’ initialized โ†’ ACTIVE
  • Pagination โ€” cursor-based across all list methods
  • Session state machine โ€” INITIALIZING โ†’ ACTIVE โ†’ CLOSED
  • CORS & origin validation
  • DNS rebinding protection
  • Accept header strict validation (406)
  • Pending request timeout (60s)
  • SSE resumability via Last-Event-ID

โœ… Tools

  • tools/list โ€” paginated with nextCursor
  • tools/call โ€” returns CallToolResult with isError
  • outputSchema in listing
  • annotations field
  • execution.taskSupport (forbidden/optional/required)
  • Synchronous & asynchronous handler interfaces
  • Name validation (1โ€“128 chars)
  • notifications/tools/list_changed on add/remove
  • Inline notifications + logging during tool call

โœ… Resources

  • resources/list โ€” paginated
  • resources/read โ€” text & blob content
  • resources/templates/list โ€” URI templates
  • resources/subscribe / unsubscribe
  • notifications/resources/list_changed
  • notifications/resources/updated to subscribers
  • Dynamic content via ResourceHandler interface

โœ… Prompts

  • prompts/list โ€” paginated with nextCursor
  • prompts/get โ€” invokes prompt resolver
  • notifications/prompts/list_changed

โœ… Tasks

  • tasks/list, tasks/get, tasks/cancel, tasks/result
  • State machine enforcement โ€” SUBMITTED โ†’ WORKING โ†’ COMPLETED/FAILED/CANCELLED
  • notifications/tasks/status broadcast on every transition
  • Task Janitor for stale tasks
  • execution.taskSupport per tool (forbidden/optional/required)
  • TasksExtension โ€” negotiable extension exposing create_task tool + task://{id} resource template
  • Extension-gated tool visibility (hidden from un-negotiated clients)

โœ… Logging & Observability

  • logging/setLevel per session
  • notifications/message emitted above threshold
  • Progress notifications

โœ… Client Communication

  • sampling/createMessage โ€” server โ†’ client request
  • Elicitation โ€” form mode
  • notifications/cancelled โ€” bidirectional
  • notifications/tasks/status from client

โœ… Transport & I/O

  • Netty 4.2
  • io_uring / epoll / kqueue / nio auto-detection
  • Platform-thread event loops + virtual-thread handlers
  • TCP_NODELAY, SO_KEEPALIVE
  • Channel writability backpressure (setAutoRead)
  • Configurable idle timeouts (reader/writer)

โœ… Session Management

  • Stateless mode โ€” skip sessions for serverless
  • IN_MEMORY session store (ConcurrentHashMap)
  • Session Janitor โ€” 5s sweep, 30s TTL
  • SSE disconnect โ‰  session removal (supports reconnect)
  • Event log replay on reconnection

Installation

Requirements: JDK 25+

Maven

<dependency>
    <groupId>dev.tachyonmcp</groupId>
    <artifactId>tachyon-server</artifactId>
    <version>1.0.0-alpha.1</version>
</dependency>

Build from source

git clone https://github.com/kpavlov/tachyon.git
cd tachyon
mvn install -pl tachyon-mcp-server -DskipTests

Quick Start

Minimal server with tool

import dev.tachyonmcp.server.TachyonMcpServer;
import dev.tachyonmcp.server.features.tools.AbstractSyncToolHandler;
import dev.tachyonmcp.server.features.tools.ToolDescriptor;
import dev.tachyonmcp.server.features.tools.ToolResult;
import dev.tachyonmcp.server.session.McpContext;
import tools.jackson.databind.node.JsonNodeFactory;

void main() {
    var schema = JsonNodeFactory.instance.objectNode();
    schema.put("type", "object");
    schema.putObject("properties").putObject("city").put("type", "string");

    TachyonMcpServer.builder()
        .name("weather-mcp")
        .tool(new AbstractSyncToolHandler(
            ToolDescriptor.builder("get_forecast")
                .description("Get weather forecast")
                .inputSchema(schema)
                .build()) {
            @Override
            public Object handle(McpContext ctx, Object args) {
                return ToolResult.text("โ˜€๏ธ 22ยฐC");
            }
        })
        .stateless(true) // start in stateless node (no sessions)
        .port(8080) // bind to 1270.0.1:8080
        .bind();
}

With TasksExtension (negotiable)

var handle = TachyonMcpServer.builder()
    .extension(new TasksExtension())   // exposes create_task tool + task://{id} resource
    .port(8080)
    .bind();

Clients that include "extensions": {"io.modelcontextprotocol/tasks": {}} in their
initialize capabilities receive the extension's tool and resource template.
Clients that don't negotiate the extension see standard MCP tasks via tasks/list / tasks/get.

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
  • Batch flushing โ€” ctx.write() accumulates, single ctx.flush() on boundary
  • Minimal allocations โ€” McpEndpointHandler is @Sharable, no per-request handler creation
  • Virtual threads โ€” handlers offloaded from event loop, no manual thread pools
  • JSON-RPC โ€” Jackson streaming codec, no ObjectMapper.

Gaps & Limitations

  • Rate limiting (Medium) โ€” Not yet implemented
  • URL elicitation mode / -32042 error (Medium) โ€” Form mode works, URL mode missing
  • 2026-07-28 draft protocol version (Low) โ€” Not negotiable; version-gated features ready
  • Stale session on re-initialize (Low) โ€” 30s TTL lingering, affects reconnect only

FAQ

Can I deploy to AWS Lambda?

Yes. Use stateless(true) to skip session persistence. Each invocation processes one request independently.

Does it support HTTP/2?

Not yet. The current pipeline targets HTTP/1.1; HTTP/2 upgrade is a pipeline configuration change comming soon.

How do I write a custom tool?

Extend AbstractSyncToolHandler or AbstractAsyncToolHandler, passing a ToolDescriptor:

class MyTool extends AbstractSyncToolHandler {
    MyTool() {
        super(ToolDescriptor.builder("my_tool")
                .description("Does something useful")
                .inputSchema(buildSchema())
                .build());
    }

    @Override
    public Object handle(McpContext ctx, Object args) throws Exception {
        return CallToolResult.ofText("done");
    }

    private static JsonNode buildSchema() {
        var s = JsonNodeFactory.instance.objectNode();
        s.put("type", "object");
        return s;
    }
}

How do I implement a custom resource?

server.resources().add(
    ResourceDescriptor.of("custom://data"),
    (ctx, req) -> new TextResourceContents("content", req.uri(), "text/plain", null));

License

Tachyon MCP is available under the terms of the Apache 2.0.

Reviews (0)

No results found