fastMCP4J

Fast lightweight Java MCP server framework - Build Model Context Protocol servers with minimal boilerplate and full TypeScript SDK compatibility

FastMCP4J

Java library for building MCP servers — annotation-driven, minimal dependencies

AI Agents → Share this skill with Claude for code generation

Java Maven License Tests

Lightweight. 12 dependencies. No containers.

Just annotate and run. See below →

Note: Beta release (v0.3.1-beta) — Multi-class modules, bash tools, telemetry. API stable.


Quick Start (2 minutes)

Add dependency

Maven:

<dependency>
    <groupId>io.github.terseprompts.fastmcp</groupId>
    <artifactId>fastmcp-java</artifactId>
    <version>0.3.1-beta</version>
</dependency>

Gradle:

dependencies {
    implementation 'io.github.terseprompts.fastmcp:fastmcp-java:0.3.1-beta'
}

Create your server

@McpServer(name = "Assistant", version = "1.0")
public class MyAssistant {

    @McpTool(description = "Summarize text")
    public String summarize(@McpParam(description = "Text") String text) {
        return "Summary: " + text.substring(0, Math.min(100, text.length()));
    }

    public static void main(String[] args) {
        FastMCP.server(MyAssistant.class)
            .stdio()           // or .sse() or .streamable()
            .run();
    }
}

Run it

mvn exec:java -Dexec.mainClass="com.example.MyAssistant"

That's it. Your MCP server is running.

Working example: EchoServer.java


Who This Is For

You want to...FastMCP4J
Expose Java tools to AI agents✅ Perfect fit
Build MCP servers quickly✅ Annotation-driven, minimal code
Add MCP to existing Spring app✅ Drop-in, no framework lock-in
Lightweight MCP-only solution✅ 12 dependencies, not 50+
Fast startup & low memory✅ <500ms cold start, ~64MB

How to Use

Make a tool

@McpTool(description = "Add two numbers")
public int add(int a, int b) {
    return a + b;
}

Make it async

@McpTool(description = "Process data")
@McpAsync  // ← just add this
public Mono<String> process(@McpContext Context ctx, String input) {
    return Mono.fromCallable(() -> {
        ctx.reportProgress(50, "Processing...");
        return slowOperation(input);
    });
}

Add memory

@McpServer(name = "MyServer", version = "1.0")
@McpMemory  // ← just add this
public class MyServer {
    // AI now remembers things across sessions
}

Add all built-in tools

@McpServer(name = "MyServer", version = "1.0")
@McpMemory     // AI remembers
@McpTodo       // AI manages tasks
@McpPlanner    // AI breaks tasks into steps
@McpFileRead   // AI reads your files
@McpFileWrite  // AI writes files
public class MyServer {
    // All tools enabled, zero implementation needed
}

Organize tools across multiple classes

@McpServer(
    name = "MyServer",
    version = "1.0",
    modules = {StringTools.class, MathTools.class}  // Explicit modules
)
public class MyServer {
    // Tools from StringTools and MathTools are included
}

Or use package scanning for auto-discovery:

@McpServer(
    name = "MyServer",
    version = "1.0",
    scanBasePackage = "com.example.tools"  // Auto-discover all tools
)
public class MyServer {
    // All @McpTool classes in the package are included
}

Add bash/shell execution

@McpServer(name = "MyServer", version = "1.0")
@McpBash(timeout = 30)  // Shell command execution with security guardrails
public class MyServer {
    // Provides 'execute_command' tool with OS-aware shell selection
}

Add telemetry

@McpServer(name = "MyServer", version = "1.0")
@McpTelemetry(enabled = true, exportConsole = true)  // Metrics & tracing
public class MyServer {
    // Automatic tool invocation tracking with console export
}

Choose transport

FastMCP.server(MyServer.class)
    .stdio()       // For CLI tools, local agents
    .sse()         // For web clients, long-lived connections
    .streamable()  // For bidirectional streaming (recommended)
    .run();

Configure port, timeout, capabilities

FastMCP.server(MyServer.class)
    .port(3000)                              // HTTP port
    .requestTimeout(Duration.ofMinutes(5))   // Request timeout
    .keepAliveSeconds(30)                     // Keep-alive interval
    .capabilities(c -> c
        .tools(true)
        .resources(true, true)
        .prompts(true))
    .run();

Icons

Add visual polish to your server, tools, resources, and prompts.

@McpServer(
    name = "my-server",
    icons = {
        "data:image/svg+xml;base64,...:image/svg+xml:64x64:light",
        "data:image/svg+xml;base64,...:image/svg+xml:64x64:dark"
    }
)
@McpTool(
    description = "My tool",
    icons = {"https://example.com/icon.png"}
)
public class MyServer { }

Resources & Prompts

@McpResource(uri = "config://settings")
public String getSettings() {
    return "{\"theme\": \"dark\"}";
}

@McpPrompt(name = "code-review")
public String codeReviewPrompt(@McpParam(description = "Code to review") String code) {
    return "Review this code:\n" + code;
}

Built-in Tools

Add ONE annotation, get complete functionality.

AnnotationTools You Get
@McpMemorylist, read, create, replace, insert, delete, rename
@McpTodoadd, list, updateStatus, updateTask, delete, clearCompleted
@McpPlannercreatePlan, listPlans, getPlan, addTask, addSubtask
@McpFileReadreadLines, readFile, grep, getStats
@McpFileWritewriteFile, appendFile, writeLines, deleteFile, createDirectory

Annotations Reference

AnnotationTargetPurpose
@McpServerTYPEDefine your MCP server
@McpToolMETHODExpose as callable tool
@McpResourceMETHODExpose as resource
@McpPromptMETHODExpose as prompt template
@McpParamPARAMETERAdd description, examples, constraints, defaults
@McpAsyncMETHODMake tool async (return Mono<?>)
@McpContextPARAMETERInject request context
@McpPreHookMETHODRun before tool call (params: toolName, order)
@McpPostHookMETHODRun after tool call (params: toolName, order)
@McpBashTYPEEnable bash/shell command execution tool
@McpTelemetryTYPEEnable metrics and tracing (params: enabled, exportConsole, exportOtlp, sampleRate)
@McpMemoryTYPEEnable memory tools
@McpTodoTYPEEnable todo/task management tools
@McpPlannerTYPEEnable planning tools
@McpFileReadTYPEEnable file reading tools
@McpFileWriteTYPEEnable file writing tools

@McpParam advanced options:

@McpTool(description = "Create task")
public String createTask(
    @McpParam(
        description = "Task name",
        examples = {"backup", "sync"},
        constraints = "Cannot be empty",
        defaultValue = "default",
        required = false
    ) String taskName
) { return "Created: " + taskName; }

Hooks — Run Code Before/After Tools

Two hook types supported:

@McpPreHook — Runs before tool is called. Receives Map<String, Object> arguments.

@McpPostHook — Runs after tool completes. Receives Map<String, Object> arguments, Object result.

Use for logging, validation, authentication, audit trails, metrics.

@McpServer(name = "MyServer", version = "1.0")
public class MyServer {

    @McpTool(description = "Calculate")
    public int calculate(int x, int y) {
        return x + y;
    }

    // Run before ALL tools (*)
    @McpPreHook(toolName = "*", order = 1)
    void authenticate(Map<String, Object> args) {
        String token = (String) args.get("token");
        if (!isValid(token)) throw new SecurityException("Unauthorized");
    }

    // Run after specific tool only
    @McpPostHook(toolName = "calculate", order = 1)
    void logResult(Map<String, Object> args, Object result) {
        System.out.println("Result: " + result);
    }

    public static void main(String[] args) {
        FastMCP.server(MyServer.class).stdio().run();
    }
}

Hook options:

  • toolName — Target specific tool name, or "*" for all tools. Empty = inferred from method name
  • order — Execution priority (lower = first). Default: 0

Hook parameters:

  • Pre-hook: Map<String, Object> arguments — Tool input arguments
  • Post-hook: Map<String, Object> arguments, Object result — Input + output

Context Access — Request Metadata

@McpContext — Inject request context into your tool.

Access client info, session data, request metadata.

@McpServer(name = "MyServer", version = "1.0")
public class MyServer {

    @McpTool(description = "Get client info")
    public String getClientInfo(@McpContext Context context) {
        return "Client: " + context.getClientId();
    }

    @McpTool(description = "Get session ID")
    public String getSessionId(@McpContext Context context) {
        return "Session: " + context.getSessionId();
    }

    @McpTool(description = "Read file with context")
    public String readFile(@McpContext Context context, String path) {
        context.info("Reading file: " + path);

        // Access request headers (e.g., for auth)
        Map<String, String> headers = context.getRequestHeaders();
        String authHeader = headers.get("Authorization");

        // ... read file
        return "Content";
    }

    public static void main(String[] args) {
        FastMCP.server(MyServer.class).stdio().run();
    }
}

Context capabilities:

  • getClientId() — Client identifier
  • getSessionId() — Session identifier
  • getToolName() — Current tool name
  • getRequestHeaders() — Client request headers (e.g., auth tokens, custom headers)
  • info(String) — Log info message
  • warning(String) — Log warning
  • error(String) — Log error
  • reportProgress(int, String) — Report progress percentage
  • listResources() — List available resources
  • listPrompts() — List available prompts

New Features

@McpBash — Shell Command Execution

Execute shell commands with OS-aware shell selection and built-in security guardrails.

@McpServer(name = "MyServer", version = "1.0")
@McpBash(
    timeout = 30,                          // Command timeout in seconds
    visibleAfterBasePath = "/sandbox/*",   // Whitelist allowed directories
    notAllowedPaths = {"/etc", "/root"}    // Blacklist dangerous paths
)
public class MyServer { }

Security features:

  • Directory validation (whitelist/blacklist)
  • Dangerous command blocking (rm -rf, wget, curl, ssh, etc.)
  • Directory traversal prevention
  • Cross-platform path handling (Windows/Unix)

Supported shells:

  • Windows: cmd.exe
  • macOS: /bin/zsh
  • Linux: /bin/bash

@McpTelemetry — Metrics & Tracing

Collect metrics and traces for tool invocations.

@McpServer(name = "MyServer", version = "1.0")
@McpTelemetry(
    enabled = true,
    exportConsole = true,              // Human-readable output
    exportOtlp = false,                // OpenTelemetry export
    sampleRate = 1.0,                  // 100% sampling
    includeArguments = false,          // Don't log sensitive args
    metricExportIntervalMs = 60_000
)
public class MyServer { }

Collected metrics:

  • Tool invocation counters
  • Execution duration histograms
  • Error rates

Multi-Class Tool Organization

Split tools across multiple classes for better organization.

Manual modules (fast, explicit):

@McpServer(
    name = "MyServer",
    version = "1.0",
    modules = {StringTools.class, MathTools.class}
)

Package scanning (convenient):

@McpServer(
    name = "MyServer",
    version = "1.0",
    scanBasePackage = "com.example.tools"
)

Why FastMCP4J?

Less code

Raw MCP SDK: 35+ lines per tool FastMCP4J: ~8 lines per tool

Lightweight

FrameworkDependenciesBest For
Spring AI50+ jarsFull-stack AI apps
LangChain4j30+ jarsEnterprise AI pipelines
Quarkus AI40+ jarsCloud-native microservices
FastMCP4J12 jarsMCP servers only

Fast & focused

  • Cold start: <500ms
  • Tool invocation: <5ms
  • Memory: ~64MB
  • Purpose-built for MCP — not a general AI framework

Documentation


License

MIT © 2026


Less boilerplate. More shipping.

Get startedExamplesDocs

Made with ❤️ for the Java community

Máy chủ liên quan

NotebookLM Web Importer

Nhập trang web và video YouTube vào NotebookLM chỉ với một cú nhấp. Được tin dùng bởi hơn 200.000 người dùng.

Cài đặt tiện ích Chrome