fastMCP4J

Framework ligero y rápido de servidor MCP en Java: crea servidores del Protocolo de Contexto de Modelo con mínimo código repetitivo y compatibilidad total con el SDK de TypeScript.

Documentación

FastMCP4J

Maven Central Java CI License Tests MCP Marketplace

Anota una clase Java. Despliega un servidor MCP.

Herramientas, recursos, prompts, memoria — y una terminal bash aislada que no puede tocar tu máquina. Sin código repetitivo, sin contenedores, sin un framework de 50 JARs.

Agentes de IA → Comparte esta habilidad con Claude para generación de código

An AI agent driving the sandboxed bash tool: virtual identity, read-only project mounts, network denied, destructive commands blocked — writes stay in the sandbox.

FastMCP4J es un SDK basado en anotaciones para el Protocolo de Contexto de Modelos (especificación 2.0.1) en Java 17+. Una anotación convierte una clase en un servidor MCP; una más le da a tu agente de IA una terminal real — un sandbox de bash donde el host es inalcanzable por construcción. Arranque en frío en menos de 500 ms, doce dependencias, todo comprobable en proceso.

Estado: beta (v0.5.0-beta) — API estable, 235 pruebas pasando, publicado en Maven Central.


Inicio rápido (2 minutos)

Maven

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

Gradle

implementation 'io.github.terseprompts.fastmcp:fastmcp-java:0.5.0-beta'

Esa es toda la historia de instalación: Java 17+, un artefacto en Maven Central, SDK de Java MCP 2.0.1 por debajo. Sin procesador de anotaciones, sin paso de generación de código, sin runtime de contenedores.

Crea tu servidor

@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();
    }
}
mvn exec:java -Dexec.mainClass="com.example.MyAssistant"

Eso es todo. Tu servidor MCP está en ejecución.

Ejemplo funcional: EchoServer.java


Por qué existe esto

Cada equipo de Java que conecta agentes de IA a herramientas enfrenta la misma elección, y cada opción duele:

SDK MCP puroSpring AI / LangChain4jFastMCP4J
Líneas por herramienta35+varía, más pegamento de framework~8
Dependencias1 + tu paciencia30–50+ JARs12 JARs
Arranquerápidodel tamaño de un framework<500 ms, ~64 MB
Bash aisladohazlo tú mismono incluido✅ integrado (bashkit4j)
Memoria / todo / planificador / herramientas de archivos integradasnono✅ una anotación cada una
Bloqueoningunoframeworkninguno — MCP entra, MCP sale

Antes: un día de configuración de esquemas JSON por herramienta, y el acceso al shell significa que un prompt malicioso es un nodo caído. Después: anotaciones el martes, agentes en producción el miércoles — y la terminal que usan no puede tocar tu disco.


El recorrido por la API

1 · Crea una herramienta — síncrona o asíncrona

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

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

2 · Cerebros integrados — una anotación cada uno

@McpServer(name = "MyServer", version = "1.0")
@McpMemory     // AI remembers things across sessions
@McpTodo       // AI manages tasks
@McpPlanner    // AI breaks work into plans
@McpFileRead   // AI reads your files
@McpFileWrite  // AI writes files
public class MyServer {
    // complete tool sets enabled, zero implementation
}
AnotaciónHerramientas que obtienes
@McpMemorylistar, leer, crear, reemplazar, insertar, eliminar, renombrar
@McpTodoagregar, listar, actualizarEstado, actualizarTarea, eliminar, limpiarCompletadas
@McpPlannercrearPlan, listarPlanes, obtenerPlan, agregarTarea, agregarSubtarea
@McpFileReadleerLíneas, leerArchivo, grep, obtenerEstadísticas
@McpFileWriteescribirArchivo, agregarArchivo, escribirLíneas, eliminarArchivo, crearDirectorio

3 · Bash aislado — dale al agente una terminal, no tu máquina

@McpServer(name = "Reviewer", version = "1.0")
@McpBash(
    allowMountsUnder = "C:/dev",           // opt in: all it may ever see
    mounts = {"/project=C:/dev/my-app"},   // mount the project — read-only
    timeout = 30, maxCommands = 10_000     // bounds runaway scripts
)
public class Reviewer { }

Los scripts se ejecutan en un bashkit4j sandbox en memoria: bash estilo POSIX con más de 160 comandos reimplementados de forma nativa, un sistema de archivos virtual, red denegada por defecto. Nunca se ejecuta bash real. Luego el agente llama a la herramienta bash:

grep -rn TODO /project/src | head -5      # real files, zero risk
echo "findings..." > /notes.md            # writes stay in the sandbox
Shell del host (ProcessBuilder, Docker)Modo sandbox
Bash real en el host✅ se ejecuta — superficie de ataque completa❌ nunca — bash reimplementado de forma nativa
Sistema de archivos del host visible✅ todo❌ invisible hasta que lo montas, solo lectura por defecto
Procesos del SO por comando✅ uno por llamada❌ cero — en proceso
Acceso a red✅ abierto❌ denegado por defecto
Un script maliciosonodo caídosandbox reiniciado

El estado persiste entre llamadas (directorio actual, entorno, archivos) — los flujos de trabajo de agentes de varios pasos funcionan. Los montajes se aplican dentro de la biblioteca nativa: canonicalizados, seguros contra enlaces simbólicos, e imposibles sin allowMountsUnder. ¿Necesitas el shell real para automatización confiable? mode = BashMode.HOST mantiene la herramienta heredada con sus protecciones de rutas.

El modo sandbox requiere la dependencia opcional io.github.terseprompts:bashkit4j:0.2.0 — las bibliotecas nativas para Windows/Linux/macOS (x86-64 + ARM64) están incluidas y se detectan automáticamente.

🔭 Alcance futuro — un tercer modo, BashMode.DOCKER. La escalera de aislamiento gana un peldaño más: HOST = la computadora completa (uso confiable) → SANDBOX = una computadora virtual, sin ejecución de código real (por defecto) → DOCKER = bash real dentro de una jaula de contenedor por sesión. El esquema: un contenedor por sesión MCP, creado de forma diferida y endurecido en ejecución (--network none --memory 512m --cpus 1 --pids-limit 64 --security-opt no-new-privileges --read-only --tmpfs /tmp); el comando se pasa como un solo elemento argv (sin interpolación del shell del host → sin superficie de inyección); el tiempo de espera se aplica dentro del contenedor para que el tiempo de pared sobreviva a un fallo del servidor; códigos de salida con nombre ([exit 124: timed out], [exit 137: OOM]), salida limitada, expulsión por TTL de inactividad con un respaldo de reaper — los contenedores permanecen sin estado, el estado duradero vive solo en el árbol de trabajo montado. La configuración sigue siendo solo de entorno (FASTMCP_DOCKER_IMAGE, tiempo de espera). No iniciado — consulta Hoja de ruta; se busca ayuda.

4 · Elige un transporte

FastMCP.server(MyServer.class)
    .stdio()       // CLI tools, local agents
    .sse()         // web clients, long-lived connections
    .streamable()  // bidirectional streaming (recommended)
    .run();
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();

5 · Recursos y 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;
}

6 · Hooks — antes/después de cada llamada a herramienta

// 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 a specific tool only
@McpPostHook(toolName = "calculate", order = 1)
void logResult(Map<String, Object> args, Object result) {
    System.out.println("Result: " + result);
}
  • toolName — herramienta objetivo, o "*" para todas (vacío = inferido del nombre del método)
  • order — prioridad de ejecución, menor se ejecuta primero (por defecto 0)
  • Los pre-hooks reciben los argumentos; los post-hooks reciben argumentos + resultado

7 · Contexto de solicitud

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

Context te da getClientId(), getSessionId(), getToolName(), getRequestHeaders(), registro de info/warning/error, reportProgress, listResources(), listPrompts().

8 · Organiza a escala

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

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

9 · Iconos y telemetría

@McpServer(
    name = "my-server",
    icons = {"data:image/svg+xml;base64,...:image/svg+xml:64x64:light"}
)
@McpTelemetry(enabled = true, exportConsole = true, sampleRate = 1.0)
public class MyServer { }

La telemetría recopila contadores de invocación de herramientas, histogramas de duración y tasas de error — exportación a consola o OpenTelemetry.


Referencia de anotaciones

AnotaciónObjetivoPropósito
@McpServerTIPODefine tu servidor MCP
@McpToolMÉTODOExpón como herramienta invocable
@McpResourceMÉTODOExpón como recurso
@McpPromptMÉTODOExpón como plantilla de prompt
@McpParamPARÁMETRODescripción, ejemplos, restricciones, valores por defecto
@McpAsyncMÉTODOHaz la herramienta asíncrona (devuelve Mono<?>)
@McpContextPARÁMETROInyecta contexto de solicitud
@McpPreHook / @McpPostHookMÉTODOEjecuta código antes/después de llamadas a herramientas
@McpBashTIPOHerramienta bash — aislada (por defecto) o shell del host vía mode
@McpTelemetryTIPOMétricas y trazabilidad
@McpMemory / @McpTodo / @McpPlannerTIPOConjuntos de herramientas integrados
@McpFileRead / @McpFileWriteTIPOHerramientas de archivos integradas

Opciones avanzadas de @McpParam:

@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; }

Lo que el sandbox realmente hace (medido, no afirmado)

FastMCP4J incluye 235 pruebas (mvn test) — la suite del sandbox se ejecuta contra la biblioteca nativa real en CI de Windows y Linux, incluyendo sondas de escape deliberadas:

SondaResultado
ls / dentro del sandboxsolo raíz virtual — pom.xml, target, rutas del host ausentes
whoami / hostnameagent@sandbox — identidad virtual, no tu usuario del SO
Escribir en un montaje de solo lecturafalla; el archivo del host nunca aparece de forma demostrable
Montaje de lectura-escrituraviajes de ida y vuelta al host a través de la API de Java
cd + archivo entre llamadas a herramientaspersiste dentro de un servidor; sellado entre servidores
Script que excede el tiempo de esperael llamador recibe TIMEOUT; el sandbox se reemplaza fresco para la siguiente llamada
4 llamadas a herramientas concurrentestodas se completan — las llamadas se serializan en el sandbox
Sandbox sin bashkit4j en el classpatherror de arranque claro que nombra la dependencia

Para quién es

  • Ingenieros de IA/LLM — expón servicios Java a Claude, Cursor o cualquier cliente MCP con esfuerzo a nivel de anotación.
  • Equipos que envían herramientas de agentes — memoria, todo, planificación, acceso a archivos y una terminal aislada listos para usar; hooks y telemetría para producción.
  • Plataformas conscientes de la seguridad — acceso de terminal de agentes con el host inalcanzable por construcción, no por ingeniería de prompts.
  • Bases de código existentes con Spring/DI — servidor de inserción directa, sin bloqueo de framework; tus beans se convierten en herramientas con una anotación.

Requisitos y rendimiento

Solo Java 17+ y Maven 3.8+. Especificación MCP 2.0.1 vía el SDK oficial de Java (mcp-core + mcp-json-jackson2).

  • Arranque en frío: <500 ms
  • Invocación de herramientas: <5 ms
  • Memoria: ~64 MB
  • Diseñado específicamente para MCP — no un framework general de IA

CI/CD

RamaQué se ejecuta
development (staging)Suite de pruebas completa + pruebas de integración MCP (STDIO / SSE / Streamable / Bash aislado) en cada push y PR
mainMisma suite + publicación en Maven Central (en etapas; aprobación manual en Sonatype Central)

Flujo: rama de características → development → main (lanzamiento).


Documentación


Licencia

MIT © 2026


Menos código repetitivo. Más envíos.

Comenzar • Ejemplos • Documentación

Hecho con ❤️ para la comunidad de Java