Главная / Статьи / Практические советы: Рецепт Spring AI: Защита сервера MCP с использованием OAuth

Практические советы: Рецепт Spring AI: Защита сервера MCP с использованием OAuth

Пошаговое руководство по практическим рекомендациям: Spring AI Recipe: обеспечение безопасности сервера MCP с использованием OAuth — контракты, проверки и готовые блоки кода для команд, использующих эту схему.

1607 слов

В следующих примечаниях описан практический подход к реализации «Spring AI Recipe: Защита сервера MCP с использованием OAuth». Основное внимание уделяется контрактам, проверкам и шаблонам кода, а не мотивирующим пояснениям. На этапе обзора сначала запишите контракт: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.

Создание сервера авторизации

Этап создания сервера авторизации работает наилучшим образом, если рассматривать его как объект с измеримыми показателями. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно успешный и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки. Обеспечьте доступ к инструментам с узкими схемами и чёткими метками о побочных эффектах. Хостам необходимо знать, какие вызовы изменяют состояние, прежде чем они автоматически одобрят операцию.

implementation 'org.springaicommunity:mcp-authorization-server:0.1.14'
@Configuration
@EnableWebSecurity
public class SecurityConfig {

  @Bean
  SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
        .authorizeHttpRequests(auth ->
            auth.anyRequest().authenticated())
        .formLogin(withDefaults())
        .with(
            McpAuthorizationServerConfigurer.mcpAuthorizationServer(),
            withDefaults())
        .build();
  }

}
spring:
  application:
    name: recipes-authorization-server
  security:
    oauth2:
      authorizationserver:
        client:
          default-client:
            token:
              access-token-time-to-live: 1h
            registration:
              client-id: "myclient"
              client-secret: "{noop}mysecret"
              client-authentication-methods:
                - "client_secret_basic"
              authorization-grant-types:
                - "authorization_code"
              redirect-uris:
                - "http://localhost:6274/oauth/callback"
                - "http://127.0.0.1:6274/oauth/callback"
              scopes:
                - general-access
                - meteorology
                - administration
    user:
      name: craig
      password: letmein

server:
  port: 9999

Защита сервера MCP

Этап обеспечения безопасности сервера MCP работает наилучшим образом, если рассматривать его как измеримую сферу. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-либо шаг срабатывает некорректно, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Используйте инструменты с узкими схемами и четкими метками о побочных эффектах. Хостам необходимо знать, какие вызовы изменяют состояние, прежде чем они автоматически одобрят действие.

implementation 'org.springaicommunity:mcp-server-security:0.1.14'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:9999
@Configuration
@EnableWebSecurity
class McpSecurityConfig {

  @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
  private String issuerUrl;

  @Bean
  SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
        .authorizeHttpRequests(auth ->
            auth.anyRequest().authenticated())
        .with(
            McpServerOAuth2Configurer.mcpServerOAuth2(),
            (mcpAuthorization) -> {
              mcpAuthorization.authorizationServer(issuerUrl);
            }
        )
        .build();
  }

}

Тестирование сервера MCP

Этап тестирования сервера MCP работает наилучшим образом, когда его рассматривают как измеримую среду. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия всем элементам, определите критерии успеха и не допускайте молчаливого частичного выполнения задач. Используйте инструменты с узкими схемами и четкими метками о побочных эффектах. У операторов должна быть возможность узнать, какие вызовы изменяют состояние, прежде чем они автоматически одобрят их. Этап тестирования сервера MCP работает наилучшим образом, когда его рассматривают как измеримую среду. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.

Защита отдельных инструментов

На этапе обеспечения безопасности отдельных инструментов необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии.

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
class SecurityConfig {

  @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
  private String issuerUrl;

  @Bean
  SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
        .authorizeHttpRequests(auth -> {
          auth.requestMatchers("/mcp").permitAll();
          auth.anyRequest().authenticated();
        })
        .with(
            McpServerOAuth2Configurer.mcpServerOAuth2(),
            (mcpAuthorization) -> {
              mcpAuthorization.authorizationServer(issuerUrl);
            }
        )
        .build();
  }

}
@PreAuthorize("hasAuthority('SCOPE_meteorology')")
@McpTool(
    name = "get-weather-for-zipcode",
    description = "Gets the weather for a given zipcode",
    annotations = @McpTool.McpAnnotations(
        openWorldHint = false,
        destructiveHint = false,
        idempotentHint = true))
Weather getWeatherForZipcode(
    @McpToolParam(description = "The zipcode to get weather for")
    String zipcode) {
  var context = SecurityContextHolder.getContext();
  var username = context.getAuthentication().getName();
  return new Weather(
      zipcode,
      "Raining cats and dogs",
      78.0f,
      username);
}

Чек-лист операционной деятельности

На этапе составления чек-листа операционной деятельности также необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии.

Записывайте времена выполнения и стоимость токенов или запросов рядом с функциональными результатами. Визуальное отображение стоимости заранее предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды.

Аутентифицируйтесь в шлюзе и повторно авторизуйтесь на уровне данных. Один только токен-носитель не является границей аренды.

Напишите краткий руководство: как обновлять ключи, как опустошать очередь, как откатывать последнюю загрузку данных.

Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять, не читая весь граф.

Аутентифицируйтесь в шлюзе и повторно авторизуйтесь на уровне данных. Один только токен-носитель не является границей аренды.

Перед внедрением стека заморозьте версии, сделайте копию «золотого» отчета для критической цепочки операций и уточните шаги возврата к предыдущему состоянию. В совместных средах необходимы ограничения на частоту запросов, проверки принадлежности пользователя и четко определенный ответственный за обновление секретов. Лучше выбирать надежность, даже если она кажется скучной, чем умные одноразовые демонстрации.

Примечание для пакета 01496ca9e17e: не храните ключи поставщика в репозитории, установите лимит токенов на одну сессию и сохраняйте отчеты рядом с фикстчерами для оценки, чтобы последующие замены моделей можно было сравнивать.

Для этапа 0 по усилению безопасности определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия файлам, определите критерии успеха и не допускайте безответственного частичного выполнения задачи.

Подробности усиления безопасности 0/819: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменение на основе фиксированного набора вопросов, а не на основе единичных примеров.

При работе над первым этапом записи по усилению безопасности сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и то, что происходит при частичной неудаче. Такой чек-лист помогает сохранять честность последующих изменений в коде. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять, не читая весь код.

Подробности усиления безопасности 1/819: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменение на основе фиксированного набора вопросов, а не на основе единичных примеров.

Второй этап усиления безопасности работает наилучшим образом, если рассматривать его как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-либо шаг срабатывает некорректно, причина сбоя должна указывать на конкретный ответственный элемент, а не на запутанную цепочку операций.

Подробности усиления безопасности 2/819: измерьте время выполнения, класс ошибки и количество использованных токенов для этой записи, затем решите, следует ли сохранять изменения, опираясь на фиксированный набор критериев, а не на устные описания.

Для третьего этапа усиления безопасности необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения, стоимость токенов или запросов. Отображение затрат на раннем этапе предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды.

Подробности усиления безопасности 3/819: измеряйте время выполнения, класс ошибок и расход токенов для данного этапа, затем принимайте решение о сохранении изменений на основе фиксированного набора критериев, а не на основе устных оценок.

При работе над четвертым этапом записки по укреплению безопасности сначала запишите условия соглашения: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки со стороны человека и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки.

Подробности укрепления безопасности 4/819: измерьте время выполнения, класс ошибки и расход токенов для данной записки, затем решите, следует ли сохранять изменение, опираясь на заранее определенный набор критериев, а не на устные оценки.

Четвертый этап записки по укреплению безопасности работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как соглашение между входными данными и проверенными выходными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не допускайте молчаливого частичного завершения работы.

Подробности усиления безопасности 5/819: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменения на основе фиксированного набора вопросов, а не на основе единичных примеров.

На этапе 6 записи о усилении безопасности определите входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять, не читая весь код.

Подробности усиления безопасности 6/819: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменения на основе фиксированного набора вопросов, а не на основе единичных примеров.