diff --git a/ee/lib/gitlab/llm/ai_gateway/completions/summarize_new_merge_request.rb b/ee/lib/gitlab/llm/ai_gateway/completions/summarize_new_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0a4a4242750e5f216a6317cc3be342b707713a7a
--- /dev/null
+++ b/ee/lib/gitlab/llm/ai_gateway/completions/summarize_new_merge_request.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module Llm
+    module AiGateway
+      module Completions
+        class SummarizeNewMergeRequest < Base
+          extend ::Gitlab::Utils::Override
+          include Gitlab::Utils::StrongMemoize
+
+          CHARACTER_LIMIT = 2000
+
+          override :inputs
+          def inputs
+            { extracted_diff: extracted_diff }
+          end
+
+          private
+
+          def extracted_diff
+            Gitlab::Llm::Utils::MergeRequestTool.extract_diff(
+              source_project: source_project,
+              source_branch: options[:source_branch],
+              target_project: resource,
+              target_branch: options[:target_branch],
+              character_limit: CHARACTER_LIMIT
+            )
+          end
+          strong_memoize_attr :extracted_diff
+
+          override :valid?
+          def valid?
+            super && extracted_diff.present?
+          end
+
+          def source_project
+            return resource unless options[:source_project_id]
+
+            source_project = Project.find_by_id(options[:source_project_id])
+
+            return source_project if source_project.present? && user.can?(:create_merge_request_from, source_project)
+
+            resource
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/ee/lib/gitlab/llm/utils/ai_features_catalogue.rb b/ee/lib/gitlab/llm/utils/ai_features_catalogue.rb
index 7e05976046db2b94ca723b0c01a0cc6dff336db2..99f244b2398eb5542af933e4d0d32fdd1fca9d85 100644
--- a/ee/lib/gitlab/llm/utils/ai_features_catalogue.rb
+++ b/ee/lib/gitlab/llm/utils/ai_features_catalogue.rb
@@ -73,6 +73,7 @@ class AiFeaturesCatalogue
           },
           summarize_new_merge_request: {
             service_class: ::Gitlab::Llm::VertexAi::Completions::SummarizeNewMergeRequest,
+            aigw_service_class: ::Gitlab::Llm::AiGateway::Completions::SummarizeNewMergeRequest,
             prompt_class: ::Gitlab::Llm::Templates::SummarizeNewMergeRequest,
             feature_category: :code_review_workflow,
             execute_method: ::Llm::SummarizeNewMergeRequestService,
diff --git a/ee/spec/lib/gitlab/llm/ai_gateway/completions/summarize_new_merge_request_spec.rb b/ee/spec/lib/gitlab/llm/ai_gateway/completions/summarize_new_merge_request_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..730f2ceeb65868b36ee328af6a43a1d21fc786b4
--- /dev/null
+++ b/ee/spec/lib/gitlab/llm/ai_gateway/completions/summarize_new_merge_request_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Llm::AiGateway::Completions::SummarizeNewMergeRequest, feature_category: :code_review_workflow do
+  let_it_be(:user) { create(:user) }
+  let_it_be(:project) { create(:project, :repository) }
+  let(:prompt_class) { Gitlab::Llm::Templates::SummarizeNewMergeRequest }
+  let(:prompt_message) do
+    build(:ai_message, :summarize_new_merge_request, user: user, resource: project, request_id: 'uuid')
+  end
+
+  let(:example_answer) { { "response" => "AI generated merge request summary" } }
+  let(:example_response) { instance_double(HTTParty::Response, body: example_answer.to_json, success?: true) }
+
+  subject(:summarize_new_merge_request) { described_class.new(prompt_message, prompt_class, options).execute }
+
+  describe '#execute' do
+    shared_examples 'makes AI request and publishes response' do
+      it 'makes AI request and publishes response' do
+        extracted_diff = Gitlab::Llm::Utils::MergeRequestTool.extract_diff(
+          source_project: options[:source_project] || project,
+          source_branch: options[:source_branch],
+          target_project: project,
+          target_branch: options[:target_branch],
+          character_limit: described_class::CHARACTER_LIMIT
+        )
+
+        expect_next_instance_of(Gitlab::Llm::AiGateway::Client) do |client|
+          expect(client)
+            .to receive(:complete)
+            .with(
+              url: "#{Gitlab::AiGateway.url}/v1/prompts/summarize_new_merge_request",
+              body: { 'inputs' => { extracted_diff: extracted_diff } }
+            )
+            .and_return(example_response)
+        end
+
+        expect(::Gitlab::Llm::GraphqlSubscriptionResponseService).to receive(:new).and_call_original
+        expect(summarize_new_merge_request[:ai_message].content).to eq(example_answer)
+      end
+    end
+
+    context 'with valid source branch and project' do
+      let(:options) do
+        {
+          source_branch: 'feature',
+          target_branch: project.default_branch,
+          source_project: project
+        }
+      end
+
+      it_behaves_like 'makes AI request and publishes response'
+    end
+
+    context 'when extracted diff is blank' do
+      let(:options) do
+        {
+          source_branch: 'does-not-exist',
+          target_branch: project.default_branch,
+          source_project: project
+        }
+      end
+
+      it 'does not make an AI request and returns nil' do
+        expect(Gitlab::Llm::AiGateway::Client).not_to receive(:new)
+        expect(summarize_new_merge_request).to be_nil
+      end
+    end
+
+    context 'when source_project_id is invalid' do
+      let(:options) do
+        {
+          source_branch: 'feature',
+          target_branch: project.default_branch,
+          source_project_id: non_existing_record_id
+        }
+      end
+
+      it_behaves_like 'makes AI request and publishes response'
+    end
+  end
+end