diff --git a/src/plugins/markdown-report/Report_markdown.mli b/src/plugins/markdown-report/Report_markdown.mli
index f76e4200aa34102efb9a561f8a183ca253cddf23..0c632a339710d55fcf6f82bcde6ad3c52fa54d15 100644
--- a/src/plugins/markdown-report/Report_markdown.mli
+++ b/src/plugins/markdown-report/Report_markdown.mli
@@ -21,6 +21,9 @@ module Title: Parameter_sig.String
 
 (** Value of [-mdr-stubs]. *)
 module Stubs: Parameter_sig.String_list
+
+(** version of mdr plugin itself *)
+val version: string
 end
 module Markdown: sig
 type align = Left | Center | Right
diff --git a/src/plugins/markdown-report/mdr_params.ml b/src/plugins/markdown-report/mdr_params.ml
index be8ef4d1c14c119e9de9be2612e0a9140571c96c..e7de9d876c360c57908221c2c933337f899b137b 100644
--- a/src/plugins/markdown-report/mdr_params.ml
+++ b/src/plugins/markdown-report/mdr_params.ml
@@ -70,3 +70,5 @@ module Stubs = String_list(
     let arg_name = "f1,...,fn"
     let help = "list of C files containing stub functions"
   end)
+
+let version = "0.1~alpha"
diff --git a/src/plugins/markdown-report/mdr_params.mli b/src/plugins/markdown-report/mdr_params.mli
index 4affc377045b0b095f3c67beb02ebbe1601f698c..e6490396557091b378b0b87caa0bd70c1742b575 100644
--- a/src/plugins/markdown-report/mdr_params.mli
+++ b/src/plugins/markdown-report/mdr_params.mli
@@ -20,3 +20,6 @@ module Title: Parameter_sig.String
 
 (** Value of [-mdr-stubs]. *)
 module Stubs: Parameter_sig.String_list
+
+(** version of mdr plugin itself *)
+val version: string
diff --git a/src/plugins/markdown-report/sarif.ml b/src/plugins/markdown-report/sarif.ml
index ce6f78f66ea7f11b8c56ae97b26ebdfe623d9872..17010d7b7c3b41279a41a3758df6decc173ab195 100644
--- a/src/plugins/markdown-report/sarif.ml
+++ b/src/plugins/markdown-report/sarif.ml
@@ -329,17 +329,23 @@ module Tool = struct
     properties: (Properties.t [@default Properties.default]);
   }[@@deriving yojson]
 
-  let default = {
-    name = "";
-    fullName = "";
-    version = "";
-    semanticVersion = "";
-    fileVersion = "";
-    downloadUri = "";
-    sarifLoggerVersion = "";
-    language = "";
-    properties = Properties.default;
-  }
+  let create
+      ~name
+      ?(fullName="")
+      ?(version="")
+      ?(semanticVersion="")
+      ?(fileVersion="")
+      ?(downloadUri="")
+      ?(sarifLoggerVersion="")
+      ?(language="en-US")
+      ?(properties=Properties.default)
+      ()
+    =
+    { name; fullName; version; semanticVersion; fileVersion;
+      downloadUri; sarifLoggerVersion; language; properties }
+
+  let default = create ~name:"" ()
+
 end
 
 module Invocation = struct
@@ -721,10 +727,68 @@ module Run = struct
     richMessageMimeType: (string [@default "text/markdown;variant=GFM" ]);
     redactionToken: (string [@default ""]);
     defaultFileEncoding: (string [@default "utf-8"]);
-    columnKind: (ColumnKind.t [@default UnicodeCodePoints]);
+    columnKind: (ColumnKind.t [@default ColumnKind.UnicodeCodePoints]);
     properties: (Properties.t [@default Properties.default]);
 }
 [@@deriving yojson]
+
+let create
+    ~tool
+    ~invocations
+    ?(conversion=Conversion.default)
+    ?(versionControlProvenance=[])
+    ?(originalUriBaseIds=Additional_properties.default)
+    ?(files=[])
+    ?(logicalLocations=[])
+    ?(graphs=[])
+    ?(results=[])
+    ?(resources=Resources.default)
+    ?instanceGuid
+    ?correlationGuid
+    ?logicalId
+    ?(description=Message.default)
+    ?automationLogicalId
+    ?baselineInstanceGuid
+    ?(architecture="")
+    ?(richMessageMimeType="text/markdown;variant=GFM")
+    ?(redactionToken="")
+    ?(defaultFileEncoding="utf-8")
+    ?(columnKind=ColumnKind.UnicodeCodePoints)
+    ?(properties=Properties.default)
+    ()
+  =
+  let instanceGuid =
+    match instanceGuid with
+    | Some guid -> guid
+    | None -> failwith "use guid generation library"
+  in
+  let correlationGuid =
+    match correlationGuid with
+    | Some guid -> guid
+    | None -> failwith "use guid generation library"
+  in
+  let logicalId =
+    match logicalId with
+    | Some id -> id
+    | None -> failwith "use id generator"
+  in
+  let automationLogicalId =
+    match automationLogicalId with
+    | Some id -> id
+    | None -> failwith "use id generator"
+  in
+  let baselineInstanceGuid =
+    match baselineInstanceGuid with
+    | Some guid -> guid
+    | None -> failwith "use guid generation library"
+  in
+  {
+    tool; invocations; conversion; versionControlProvenance; originalUriBaseIds;
+    files; logicalLocations; graphs; results; resources; instanceGuid;
+    correlationGuid; logicalId; description; automationLogicalId;
+    baselineInstanceGuid; architecture; richMessageMimeType;
+    redactionToken; defaultFileEncoding; columnKind; properties
+  }
 end
 
 module Schema = struct
@@ -733,4 +797,7 @@ module Schema = struct
     version: Version.t;
     runs: Run.t list
   } [@@deriving yojson]
+
+  let create ?(schema=Uri.Sarif_github) ?(version=Version.V2_0_0) ~runs () =
+    { schema; version; runs }
 end
diff --git a/src/plugins/markdown-report/sarif_gen.ml b/src/plugins/markdown-report/sarif_gen.ml
index d68842c4d7587ab8e49202675debf25244dfe0d7..cb02eda97e7916e133aedb87c2a724c7f3453268 100644
--- a/src/plugins/markdown-report/sarif_gen.ml
+++ b/src/plugins/markdown-report/sarif_gen.ml
@@ -1 +1,36 @@
-let generate () = Mdr_params.not_yet_implemented "Sarif_gen.generate"
+open Sarif
+
+let frama_c_sarif =
+  let name = "frama-c" in
+  let version = Config.version_and_codename in
+  let semanticVersion = Config.version in
+  let fullName = name ^ "-" ^ version in
+  let downloadUri = "https://frama-c.com/download.html" in
+  let sarifLoggerVersion = Mdr_params.version in
+  Tool.create
+    ~name ~version ~semanticVersion
+    ~fullName ~downloadUri ~sarifLoggerVersion ()
+
+let get_remarks () =
+  let f = Mdr_params.Remarks.get () in
+  if f <> "" then Parse_remarks.get_remarks f
+  else Datatype.String.Map.empty
+
+let gen_run () =
+  let tool = frama_c_sarif in
+  let invocations = [] in
+  Run.create ~tool ~invocations ()
+
+let generate () =
+  let runs = [ gen_run () ] in
+  let json = Schema.create ~runs () in
+  let out = Mdr_params.Output.get () in
+  let chan =
+    if out = "" then stdout
+    else begin
+      try open_out out
+      with Sys_error s ->
+        Mdr_params.abort "Unable to open output file %s: %s" out s
+    end
+  in
+  Yojson.Safe.to_channel chan (Schema.to_yojson json)