Skip to content

Annotation-based MCP service #6873

Description

@ikhoon

Background

Armeria gained MCP server support in #6513 — the ai/mcp module provides Armeria transports
(ArmeriaStreamableServerTransportProvider, ArmeriaStatelessServerTransport) for the
MCP Java SDK, built on top of JsonRpcService (#6504).
(Related: #6179)

However, defining tools, resources and prompts still goes through the SDK's programmatic APIs
(McpServerFeatures.SyncToolSpecification and friends), which are fairly verbose — input JSON schemas
are hand-written strings and every handler is registered manually.

Proposal

Provide an annotation-based programming model for MCP services, in the same spirit as Armeria's
annotated HTTP services and
Spring AI's MCP server annotations.
A strawman sketch:

final class MyMcpService {

    @McpTool(description = "Adds two numbers")
    public int add(@McpToolParam(description = "The first number") int a,
                   @McpToolParam(description = "The second number") int b) {
        return a + b;
    }

    @McpResource(uri = "config://{key}", description = "Returns a configuration value")
    public String config(String key) {
        return configs.get(key);
    }

    @McpPrompt(description = "Generates a greeting message")
    public String greeting(@McpArg(description = "The user's name") String name) {
        return "Hello, " + name + '!';
    }
}

Server.builder()
      .service("/mcp", McpService.builder()
                                 .annotatedService(new MyMcpService())
                                 .build())
      .build()
      .start();
  • Input JSON schemas are generated automatically from the method signature instead of hand-written
    schema strings.
  • Async support the Armeria way: CompletableFuture<T> and Publisher<T> return types.
  • Reuses the existing ai/mcp transports underneath, so both streamable (stateful) and stateless
    modes work as-is.

Notes

  • Spring AI's annotations originate from the framework-agnostic
    spring-ai-community/mcp-annotations, but that
    project has graduated into Spring AI 2.x and is no longer maintained standalone — so implementing our
    own annotations (reusing Armeria's annotated-service machinery where it makes sense) looks like the
    better long-term fit.
  • DocService integration (browsing tools/resources/prompts, debug form) would be a nice follow-up,
    similar to gRPC/Thrift support.
  • Client-side annotations (sampling / elicitation / progress handlers) are out of scope here and could
    follow later.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions