diff --git a/app/graphql/mutations/ml/model_versions/edit.rb b/app/graphql/mutations/ml/model_versions/edit.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f6bc85cc1cbf1f491273ab3fd8bed30702ea8b3b
--- /dev/null
+++ b/app/graphql/mutations/ml/model_versions/edit.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Mutations
+  module Ml
+    module ModelVersions
+      class Edit < BaseMutation
+        graphql_name 'MlModelVersionEdit'
+        include FindsProject
+
+        authorize :write_model_registry
+
+        argument :project_path, GraphQL::Types::ID,
+          required: true,
+          description: "Project the model to mutate is in."
+
+        argument :model_id, ::Types::GlobalIDType[::Ml::Model],
+          required: true,
+          description: 'Global ID of the model the version belongs to.'
+
+        argument :version, GraphQL::Types::String,
+          required: true,
+          description: 'Model version.'
+
+        argument :description, GraphQL::Types::String,
+          required: true,
+          description: 'Description of the model version.'
+
+        field :model_version,
+          Types::Ml::ModelVersionType,
+          null: true,
+          description: 'Model after mutation.'
+
+        def resolve(**args)
+          project = authorized_find!(args[:project_path])
+          model = ::Ml::Model.by_project_id_and_id(project.id, args[:model_id].model_id)
+
+          return { errors: ['Model not found'] } unless model
+
+          service_response = ::Ml::ModelVersions::UpdateModelVersionService.new(project, model.name, args[:version],
+            args[:description]).execute
+
+          if service_response.success?
+            {
+              model_version: service_response.payload,
+              errors: []
+            }
+          else
+            {
+              model_version: nil,
+              errors: service_response.errors
+            }
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 1ee9f8fa275e2ff475329855fcb6bad995cdd090..b4ab430ecf2a0c82fdd6b2dccf67ee939faabfda 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -223,6 +223,7 @@ class MutationType < BaseObject
     mount_mutation Mutations::Ml::Models::Destroy, alpha: { milestone: '16.10' }
     mount_mutation Mutations::Ml::Models::Delete, alpha: { milestone: '17.0' }
     mount_mutation Mutations::Ml::ModelVersions::Create, alpha: { milestone: '17.1' }
+    mount_mutation Mutations::Ml::ModelVersions::Edit, alpha: { milestone: '17.4' }
     mount_mutation Mutations::Ml::ModelVersions::Delete, alpha: { milestone: '17.0' }
     mount_mutation Mutations::BranchRules::Delete, alpha: { milestone: '16.9' }
     mount_mutation Mutations::Pages::Deployment::Delete, alpha: { milestone: '17.1' }
diff --git a/app/helpers/projects/ml/model_registry_helper.rb b/app/helpers/projects/ml/model_registry_helper.rb
index ee5303d8710f935c29b45296c12e3db25d3018e2..e7d35baf36fb5daea6b7831615fb8ca525f09afc 100644
--- a/app/helpers/projects/ml/model_registry_helper.rb
+++ b/app/helpers/projects/ml/model_registry_helper.rb
@@ -48,7 +48,8 @@ def show_ml_model_version_data(model_version, user)
           can_write_model_registry: can_write_model_registry?(user, project),
           import_path: model_version_artifact_import_path(project.id, model_version.id),
           model_path: project_ml_model_path(project, model_version.model),
-          max_allowed_file_size: max_allowed_file_size(project)
+          max_allowed_file_size: max_allowed_file_size(project),
+          markdown_preview_path: preview_markdown_path(project)
         }
 
         to_json(data)
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 9e9c1432a1483777a8b116daec2b98e70318d719..4df7198a5074082b73327cd2960e743b6ab5fadd 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -7123,6 +7123,32 @@ Input type: `MlModelVersionDeleteInput`
 | <a id="mutationmlmodelversiondeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
 | <a id="mutationmlmodelversiondeletemodelversion"></a>`modelVersion` | [`MlModelVersion`](#mlmodelversion) | Deleted model version. |
 
+### `Mutation.mlModelVersionEdit`
+
+DETAILS:
+**Introduced** in GitLab 17.4.
+**Status**: Experiment.
+
+Input type: `MlModelVersionEditInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationmlmodelversioneditclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationmlmodelversioneditdescription"></a>`description` | [`String!`](#string) | Description of the model version. |
+| <a id="mutationmlmodelversioneditmodelid"></a>`modelId` | [`MlModelID!`](#mlmodelid) | Global ID of the model the version belongs to. |
+| <a id="mutationmlmodelversioneditprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the model to mutate is in. |
+| <a id="mutationmlmodelversioneditversion"></a>`version` | [`String!`](#string) | Model version. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationmlmodelversioneditclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationmlmodelversionediterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationmlmodelversioneditmodelversion"></a>`modelVersion` | [`MlModelVersion`](#mlmodelversion) | Model after mutation. |
+
 ### `Mutation.namespaceBanDestroy`
 
 Input type: `NamespaceBanDestroyInput`
diff --git a/spec/helpers/projects/ml/model_registry_helper_spec.rb b/spec/helpers/projects/ml/model_registry_helper_spec.rb
index 415e98741698bd81fae15ae5a0f6046a873247a8..ec4e73ca122b02b2e46ec2b1c33945b702561926 100644
--- a/spec/helpers/projects/ml/model_registry_helper_spec.rb
+++ b/spec/helpers/projects/ml/model_registry_helper_spec.rb
@@ -99,7 +99,8 @@
         "canWriteModelRegistry" => true,
         'maxAllowedFileSize' => 10737418240,
         "importPath" => "/api/v4/projects/#{project.id}/packages/ml_models/#{model_version.id}/files/",
-        "modelPath" => "/#{project.full_path}/-/ml/models/1"
+        "modelPath" => "/#{project.full_path}/-/ml/models/1",
+        "markdownPreviewPath" => "/#{project.full_path}/-/preview_markdown"
       })
     end
 
diff --git a/spec/requests/api/graphql/mutations/ml/model_versions/edit_spec.rb b/spec/requests/api/graphql/mutations/ml/model_versions/edit_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b1e6128463b20550722fdb7d3bc2d1e851545bbc
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ml/model_versions/edit_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Editing of a machine learning model version', feature_category: :mlops do
+  include GraphqlHelpers
+  let_it_be(:model_version) { create(:ml_model_versions, :with_package, description: 'A **description**') }
+  let_it_be(:project) { model_version.project }
+  let_it_be(:current_user) { project.owner }
+  let_it_be(:guest) { create(:user) }
+
+  let(:model_id) { model_version.model.to_gid }
+  let(:version) { model_version.version }
+  let(:description) { 'A description' }
+  let(:new_description) { 'A **new** description' }
+
+  let(:edit_input) do
+    { project_path: project.full_path, description: new_description, model_id: model_id, version: version }
+  end
+
+  let(:mutation) { graphql_mutation(:ml_model_version_edit, edit_input, nil, ['version']) }
+  let(:mutation_response) { graphql_mutation_response(:ml_model_version_edit) }
+
+  context 'when user is not allowed write changes' do
+    before do
+      allow(Ability).to receive(:allowed?).and_call_original
+      allow(Ability).to receive(:allowed?)
+                          .with(current_user, :write_model_registry, project)
+                          .and_return(false)
+    end
+
+    it_behaves_like 'a mutation that returns a top-level access error'
+  end
+
+  context 'when the user is not part of the project' do
+    it 'does not update description' do
+      post_graphql_mutation(mutation, current_user: guest)
+      expect { mutation }.to not_change { model_version.reload.description }
+      expect(mutation_response).to be_nil
+    end
+  end
+
+  context 'when the user is authenticated' do
+    context 'when the model does not exist' do
+      let(:model_id) { "gid://gitlab/Ml::Model/0" }
+
+      it 'returns an error' do
+        post_graphql_mutation(mutation, current_user: current_user)
+
+        expect(mutation_response['errors']).to match_array(['Model not found'])
+      end
+    end
+
+    context 'when the model exists' do
+      it 'updates the model description' do
+        post_graphql_mutation(mutation, current_user: current_user)
+
+        expect(mutation_response['errors']).to be_empty
+
+        model_version.reload
+        expect(model_version.description).to eq(new_description)
+      end
+    end
+
+    context 'when the model is not part of the project' do
+      let(:project) { create(:project) }
+
+      before do
+        post_graphql_mutation(mutation, current_user: current_user)
+      end
+
+      it_behaves_like 'a mutation that returns a top-level access error'
+    end
+
+    context 'when the update service fails' do
+      before do
+        allow_next_instance_of(::Ml::ModelVersions::UpdateModelVersionService) do |instance|
+          allow(instance).to receive(:execute).and_return(
+            ServiceResponse.error(message: 'Model update failed')
+          )
+        end
+      end
+
+      it 'returns an error' do
+        post_graphql_mutation(mutation, current_user: current_user)
+
+        expect(mutation_response['errors']).to match_array(['Model update failed'])
+        expect(mutation_response['modelVersion']).to be_nil
+      end
+    end
+  end
+end