MCP сервер на Spring Boot: пошаговый гайд за вечер | AiManual
AiManual Logo Ai / Manual.
22 Июн 2026 Гайд

Как сделать MCP-сервер из Spring-сервиса за вечер: пошаговое руководство с кодом

Превратите ваш Spring-микросервис в MCP-сервер для AI-агентов. Полное руководство с кодом, аннотациями и разбором ошибок. Актуально на 2026 год.

Реклама
partv1

Ваш Spring-сервис общается с ИИ? Нет — вот как это исправить за вечер

Сценарий типичного Java-разработчика в 2026 году: вы потратили месяцы на идеальный микросервис с Spring Boot. Там есть REST-контроллеры, JPA-репозитории, кэш, очереди. Сервис умеет всё — от расчёта кредитного рейтинга до генерации PDF-отчётов. Но приходит AI-агент (Claude, GPT-5, Llama 4) и говорит: «Дай мне доступ к твоим данным и функциям». И тут вы понимаете: REST API — это как записка на папирусе. Агенту нужно что-то более родное — MCP.

Суть: MCP (Model Context Protocol) — это стандарт, который позволяет LLM напрямую вызывать функции вашего сервиса, как будто это методы в коде агента. Никаких parse JSON, curl, токенов. Просто tool call.

Я покажу, как за один вечер обернуть ваш Spring-сервис в MCP-сервер. Без магии, с реальным кодом и разбором трёх граблей, на которые я сам наступил.

Проблема: REST умер для AI-агентов (ну почти)

Любой LLM умеет вызывать функции через tool calling. Но чтобы подключить ваш Spring-сервис, приходится:

  • Писать отдельный слой для генерации JSON Schema каждой ручки.
  • Кормить агента длиннющим промптом с описанием API.
  • Терпеть ошибки из-за несовпадения форматов.

MCP решает это одним махом: ваш сервис сам говорит агенту «вот мои инструменты» через стандартный протокол. Один раз написали — подключайте любой LLM, от Claude Code до самописного агента на Python.

Решение: Spring Boot + MCP Java SDK = 40 минут

Берём Spring Boot 3.5.0 (на дворе 2026, ребята, 3.x — стабильный мейнстрим), добавляем MCP Java SDK 0.8.0, пишем 50 строк конфигурации — и ваш @RestController становится MCP-сервером.

⚠️ Предупреждение: Не пытайтесь просто навесить аннотацию @MCPTool над существующими контроллерами — вы сломаете всю логику. Нужна правильная прослойка.

1 Подготовка: проект и зависимости

Создаём обычный Spring Boot проект. Gradle или Maven — неважно. Добавляем в build.gradle:

implementation 'org.springframework.boot:spring-boot-starter-web:3.5.0'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.modelcontextprotocol:mcp-java-sdk:0.8.0'
implementation 'com.fasterxml.jackson.core:jackson-databind'

Обратите внимание: mcp-java-sdk — это официальная библиотека от Anthropic, которая даёт готовые классы для MCP транспорта (STDIO и SSE). Нам понадобится SSE-транспорт, чтобы сервис работал как самостоятельный HTTP-сервер.

💡
Для локальной разработки используйте STDIO — это проще. Но в продакшне берите SSE, чтобы агент мог подключаться удалённо.

2 Скелет MCP-сервера: пишем конфигурацию

Создаём класс McpServerConfig:

@Configuration
public class McpServerConfig {

    @Bean
    public McpServer mcpServer(McpTransport transport, List<ToolProvider> providers) {
        return new McpServer.Builder()
                .transport(transport)
                .serverInfo("spring-mcp-server", "1.0.0")
                .toolProviders(providers)
                .build();
    }

    @Bean
    @Profile("sse")
    public McpTransport sseTransport() {
        return new SseServerTransport("/mcp/v1/messages");
    }

    @Bean
    @Profile("stdio")
    public McpTransport stdioTransport() {
        return new StdioServerTransport();
    }
}

Здесь два профиля — для прода и дебага. Мой совет: сразу настраивайте оба.

3 Tool Provider: как сделать из любой Spring-бины инструмент MCP

Самый важный класс. Реализуем ToolProvider и оборачиваем через reflection вызовы ваших сервисов. Но проще — использовать готовый SpringToolProvider из SDK (если есть). На момент 2026 года в SDK есть базовый класс, который ищет аннотацию @McpTool. Давайте сделаем свой, чтобы контролировать процесс:

@Component
public class MyToolProvider implements ToolProvider {

    private final YourBusinessService service;

    public MyToolProvider(YourBusinessService service) {
        this.service = service;
    }

    @Override
    public List<Tool> getTools() {
        return List.of(
                new Tool(
                        "calculate_credit_score",
                        "Рассчитывает кредитный рейтинг по данным клиента",
                        new JsonObject(), // схема входных параметров (JSON Schema)
                        args -> {
                            String clientId = args.getString("clientId");
                            CreditScore score = service.calculate(clientId);
                            return new ContentResult(Map.of(
                                    "score", score.getValue(),
                                    "level", score.getLevel().name()
                            ));
                        }
                ),
                new Tool(
                        "generate_pdf",
                        "Генерирует PDF-отчёт для клиента",
                        new JsonObject(),
                        args -> {
                            byte[] pdf = service.generateReport(args.getString("template"));
                            return new ContentResult(Map.of("file", Base64.getEncoder().encodeToString(pdf)));
                        }
                )
        );
    }
}

Внимание на JSON Schema. В реальном коде нужно её правильно построить — иначе агент не поймёт, какие параметры передавать. SDK включает утилиты JsonSchemaBuilder:

JsonObject inputSchema = new JsonSchemaBuilder()
        .addProperty("clientId", SchemaType.STRING, "ID клиента")
        .addRequired("clientId")
        .build();

4 Запускаем и проверяем с Claude Desktop

После старта вашего Spring Boot приложения (например, --spring.profiles.active=sse) MCP-сервер слушает на порту 8080 (по умолчанию). Откройте Claude Desktop, добавьте новый MCP-сервер:

{
  "mcpServers": {
    "my-spring-service": {
      "url": "http://localhost:8080/mcp/v1/messages",
      "transport": "sse"
    }
  }
}

Теперь в диалоге с Claude можно сказать: «Рассчитай кредитный рейтинг клиента 12345». И агент сам вызовет ваш инструмент. Магия, да? Только это не магия — это MCP.

Типичные грабли (и как на них не наступить)

Грабля 1: Неявные транзакции и потоки

Вызов инструмента может выполняться в другом потоке (если агент шлёт параллельные запросы). Spring-бины — норм, но если ваш сервис использует @Transactional, убедитесь, что транзакция не заканчивается раньше времени. Лучше сделать каждый tool метод synchronized или использовать @Transactional(propagation = Propagation.REQUIRES_NEW).

Грабля 2: Сериализация циклических связей

Jackon по умолчанию падает на циклических ссылках в JPA-сущностях. Ваш tool может вернуть объект с lazy-loaded коллекцией — и JSON Schema сломается. Решение: никогда не возвращайте JPA-сущности напрямую. Используйте DTO.

// Плохо
public Tool callCalculate() {
    User user = userRepository.findById(id).get(); // LazyInitializationException
}

// Хорошо
public Tool callCalculate() {
    UserDto dto = userService.getUserSafe(id); // явный fetch
    return new ContentResult(dto);
}

Грабля 3: Долгие операции и таймауты

MCP не заточен под долгие стриминговые ответы. Если ваш tool генерирует отчёт 30 секунд, агент отвалится по таймауту. Выход — сделать асинхронный tool, который возвращает статус «задача поставлена», а потом агент дёргает другой tool для проверки результата. Это костыль, но пока MCP 0.8 не поддерживает настоящий streaming.

Лайфхак: Для длинных операций используйте подход с taskId, как в финансовых MCP-серверах.

Как протестировать MCP-сервер без агента

Не хочется каждый раз запускать Claude Desktop. Используйте утилиту mcp-cli (она идёт с SDK). Просто:

mcp-cli connect stdio java -jar my-app.jar

Или для SSE: mcp-cli connect sse http://localhost:8080/mcp/v1/messages.

Утилита покажет список инструментов и позволит вызвать их прямо из командной строки.

Что дальше: MCP и Spring AI

На 2026 год Spring AI уже поддерживает MCP на уровне McpAdapter. Вы можете подключить свой MCP-сервер к ChatClient без костылей. Подробнее — в гайде по архитектуре сайта под ИИ.

Но главный урок: MCP — это не временный хайп, а стандарт, который делает Java-бекенды родными для AI-агентов. Потратьте вечер — и ваши сервисы перестанут быть «немыми».

FAQ: быстрые ответы на вопросы, которые я слышу на митапах

ВопросОтвет
А можно без SDK?Да, напишите свой JSON-RPC хендлер. Но SDK избавляет от головной боли с транспортом.
А что с безопасностью?MCP сам не аутентифицирует. Вешайте Spring Security на эндпоинты транспорта и проверяйте API-ключ в заголовке.
А если мой сервис — реактивный WebFlux?Работает, но используйте отдельный transport: ReactiveSseServerTransport (есть в SDK).

Самый неочевидный совет, который я усвоил за полгода MCP-разработки: не делайте один огромный tool «сделай всё». Агенты лучше понимают маленькие атомарные функции. Лучше 10 простых tool'ов, чем один с 20 параметрами. Иначе LLM будет путаться — проверено.

Подписаться на канал