fastMCP4J

Framework rápido e leve para servidores MCP em Java - Construa servidores do Model Context Protocol com mínimo de código repetitivo e compatibilidade total com o SDK TypeScript

Documentação

FastMCP4J

Maven Central Java CI License Tests MCP Marketplace

Anote uma classe Java. Implante um servidor MCP.

Ferramentas, recursos, prompts, memória — e um terminal bash em sandbox que não pode tocar na sua máquina. Sem boilerplate, sem contêineres, sem framework de 50 jars.

Agentes de IA → Compartilhe esta skill com o Claude para geração 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 é um SDK orientado a anotações para o Model Context Protocol (especificação 2.0.1) em Java 17+. Uma anotação transforma uma classe em um servidor MCP; mais uma dá ao seu agente de IA um terminal real — um sandbox bash onde o host é inacessível por construção. Inicialização a frio em menos de 500 ms, doze dependências, tudo testável em processo.

Status: beta (v0.5.0-beta) — API estável, 235 testes passando, publicado no Maven Central.


Início 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'

Essa é toda a história da instalação: Java 17+, um artefato no Maven Central, MCP Java SDK 2.0.1 por baixo. Sem processador de anotações, sem etapa de geração de código, sem runtime de contêiner.

Crie seu 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"

É isso. Seu servidor MCP está rodando.

Exemplo funcional: EchoServer.java


Por que isso existe

Toda equipe Java que conecta agentes de IA a ferramentas enfrenta a mesma escolha, e toda opção dói:

SDK MCP puroSpring AI / LangChain4jFastMCP4J
Linhas por ferramenta35+varia, mais cola de framework~8
Dependências1 + sua paciência30–50+ jars12 jars
Inicializaçãorápidado tamanho de framework<500 ms, ~64 MB
Bash em sandboxfaça você mesmonão incluído✅ embutido (bashkit4j)
Memória / todo / planner / ferramentas de arquivo embutidasnãonão✅ uma anotação cada
Lock-innenhumframeworknenhum — MCP entra, MCP sai

Antes: um dia de encanamento de JSON-schema por ferramenta, e acesso ao shell significa que um prompt malicioso derruba um nó. Depois: anotações na terça, agentes em produção na quarta — e o terminal que eles usam não pode tocar no seu disco.


O tour da API

1 · Crie uma ferramenta — síncrona ou assí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 · Cérebros embutidos — uma anotação cada

@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
}
AnotaçãoFerramentas que você obtém
@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

3 · Bash em sandbox — dê ao agente um terminal, não sua 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 { }

Scripts rodam em um bashkit4j sandbox em memória: bash estilo POSIX com mais de 160 comandos reimplementados nativamente, um sistema de arquivos virtual, rede negada por padrão. Nenhum bash real é nunca iniciado. Então o agente chama a ferramenta bash:

grep -rn TODO /project/src | head -5      # real files, zero risk
echo "findings..." > /notes.md            # writes stay in the sandbox
Shell do host (ProcessBuilder, Docker)Modo sandbox
Bash real no host✅ roda — superfície de ataque completa❌ nunca — bash reimplementado nativamente
Sistema de arquivos do host visível✅ tudo❌ invisível até você montar, somente leitura por padrão
Processos do SO por comando✅ um por chamada❌ zero — em processo
Acesso à rede✅ aberto❌ negado por padrão
Um script maliciosonó derrubadosandbox redefinido

O estado persiste entre chamadas (cwd, env, arquivos) — fluxos de trabalho de agentes em várias etapas funcionam. Montagens são aplicadas dentro da biblioteca nativa: canonicalizadas, seguras contra symlink e impossíveis sem allowMountsUnder. Precisa do shell real para automação confiável? mode = BashMode.HOST mantém a ferramenta legada com seus guardrails de caminho.

O modo sandbox requer a dependência opcional io.github.terseprompts:bashkit4j:0.2.0 — bibliotecas nativas para Windows/Linux/macOS (x86-64 + ARM64) são incluídas e auto-detectadas.

🔭 Escopo futuro — um terceiro modo, BashMode.DOCKER. A escada de isolamento ganha mais um degrau: HOST = o computador completo (uso confiável) → SANDBOX = um computador virtual, sem execução de código real (padrão) → DOCKER = bash real dentro de uma jaula de contêiner por sessão. O esboço: um contêiner por sessão MCP, criado preguiçosamente e endurecido na execução (--network none --memory 512m --cpus 1 --pids-limit 64 --security-opt no-new-privileges --read-only --tmpfs /tmp); o comando passado como um único elemento argv (sem interpolação de shell do host → sem superfície de injeção); o timeout aplicado dentro do contêiner para que o relógio de parede sobreviva a uma falha do servidor; códigos de saída nomeados ([exit 124: timed out], [exit 137: OOM]), saída limitada, evicção por TTL de inatividade com um reaper de apoio — contêineres permanecem sem estado, estado durável vive apenas no worktree montado. Config permanece somente via env (FASTMCP_DOCKER_IMAGE, timeout). Não iniciado — veja Roadmap; ajuda é bem-vinda.

4 · Escolha um 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 e 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/depois de cada chamada de ferramenta

// 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 — ferramenta alvo, ou "*" para todas (vazio = inferido do nome do método)
  • order — prioridade de execução, menor roda primeiro (padrão 0)
  • Pré-hooks recebem os argumentos; pós-hooks recebem argumentos + resultado

7 · Contexto de requisição

@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 dá a você getClientId(), getSessionId(), getToolName(), getRequestHeaders(), info/warning/error logging, reportProgress, listResources(), listPrompts().

8 · Organize em 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 · Ícones e telemetria

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

A telemetria coleta contadores de invocação de ferramentas, histogramas de duração e taxas de erro — exportação para console ou OpenTelemetry.


Referência de anotações

AnotaçãoAlvoPropósito
@McpServerTYPEDefina seu servidor MCP
@McpToolMETHODExponha como ferramenta chamável
@McpResourceMETHODExponha como recurso
@McpPromptMETHODExponha como modelo de prompt
@McpParamPARAMETERDescrição, exemplos, restrições, padrões
@McpAsyncMETHODTorne a ferramenta assíncrona (retorne Mono<?>)
@McpContextPARAMETERInjete contexto de requisição
@McpPreHook / @McpPostHookMETHODExecute código antes/depois de chamadas de ferramenta
@McpBashTYPEFerramenta bash — em sandbox (padrão) ou shell do host via mode
@McpTelemetryTYPEMétricas e rastreamento
@McpMemory / @McpTodo / @McpPlannerTYPEConjuntos de ferramentas embutidos
@McpFileRead / @McpFileWriteTYPEFerramentas de arquivo embutidas

Opções avançadas do @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; }

O que o sandbox realmente faz (medido, não afirmado)

FastMCP4J inclui 235 testes (mvn test) — a suíte do sandbox roda contra a biblioteca nativa real no CI de Windows e Linux, incluindo sondas deliberadas de fuga:

SondaResultado
ls / dentro do sandboxapenas raiz virtual — pom.xml, target, caminhos do host ausentes
whoami / hostnameagent@sandbox — identidade virtual, não seu usuário do SO
Gravar em uma montagem somente leiturafalha; o arquivo do host comprovadamente nunca aparece
Montagem de leitura/gravaçãoida e volta ao host através da API Java
cd + arquivo entre chamadas de ferramentapersiste dentro de um servidor; selado entre servidores
Script excedendo o timeoutchamador recebe TIMEOUT; sandbox substituído por um novo na próxima chamada
4 chamadas de ferramenta concorrentestodas completam — chamadas serializam no sandbox
Sandbox sem bashkit4j no classpatherro claro de inicialização nomeando a dependência

Para quem é

  • Engenheiros de IA/LLM — exponha serviços Java ao Claude, Cursor ou qualquer cliente MCP com esforço de nível de anotação.
  • Equipes que entregam ferramentas de agente — memória, todo, planejamento, acesso a arquivos e um terminal em sandbox prontos; hooks e telemetria para produção.
  • Plataformas conscientes de segurança — acesso de terminal de agente com o host inacessível por construção, não por engenharia de prompt.
  • Codebases existentes com Spring/DI — servidor plug-and-play, sem lock-in de framework; seus beans viram ferramentas com uma anotação.

Requisitos e desempenho

Apenas Java 17+ e Maven 3.8+. Especificação MCP 2.0.1 via SDK Java oficial (mcp-core + mcp-json-jackson2).

  • Inicialização a frio: <500 ms
  • Invocação de ferramenta: <5 ms
  • Memória: ~64 MB
  • Feito sob medida para MCP — não é um framework geral de IA

CI/CD

BranchO que roda
development (staging)Suíte de testes completa + testes de integração MCP (STDIO / SSE / Streamable / Bash em Sandbox) em cada push e PR
mainMesma suíte + publicação no Maven Central (staged; aprovação manual no Sonatype Central)

Fluxo: branch de feature → development → main (release).


Documentação


Licença

MIT © 2026


Menos boilerplate. Mais entrega.

Comece agora • Exemplos • Docs

Feito com ❤️ para a comunidade Java