diff --git a/tools/CHANGELOG.md b/tools/CHANGELOG.md
index 184e006d8..391b24e16 100644
--- a/tools/CHANGELOG.md
+++ b/tools/CHANGELOG.md
@@ -12,6 +12,10 @@
 
 ## master
 
+#### :rocket: New Feature
+
+- Add `moduletypeid` field for explicitly annotated module type. https://github.com/rescript-lang/rescript-vscode/pull/1019
+
 ### :bug: Bug Fix
 
 - Print module structure with signature to module path. https://github.com/rescript-lang/rescript-vscode/pull/1018
diff --git a/tools/npm/Tools_Docgen.res b/tools/npm/Tools_Docgen.res
index f060ab07e..c6b7d450c 100644
--- a/tools/npm/Tools_Docgen.res
+++ b/tools/npm/Tools_Docgen.res
@@ -56,6 +56,7 @@ type rec item =
       docstrings: array<string>,
       deprecated?: string,
       name: string,
+      moduletypeid?: string,
       source: source,
       items: array<item>,
     })
diff --git a/tools/npm/Tools_Docgen.resi b/tools/npm/Tools_Docgen.resi
index c410170aa..271f65f99 100644
--- a/tools/npm/Tools_Docgen.resi
+++ b/tools/npm/Tools_Docgen.resi
@@ -55,6 +55,7 @@ type rec item =
       docstrings: array<string>,
       deprecated?: string,
       name: string,
+      moduletypeid?: string,
       source: source,
       items: array<item>,
     })
diff --git a/tools/src/tools.ml b/tools/src/tools.ml
index 9a314f92d..08837943b 100644
--- a/tools/src/tools.ml
+++ b/tools/src/tools.ml
@@ -44,7 +44,14 @@ type docItem =
           (** Additional documentation for constructors and record fields, if available. *)
     }
   | Module of docsForModule
-  | ModuleType of docsForModule
+  | ModuleType of {
+      id: string;
+      docstring: string list;
+      deprecated: string option;
+      name: string;
+      source: source;
+      items: docItem list;
+    }
   | ModuleAlias of {
       id: string;
       docstring: string list;
@@ -57,6 +64,7 @@ and docsForModule = {
   docstring: string list;
   deprecated: string option;
   name: string;
+  moduletypeid: string option;
   source: source;
   items: docItem list;
 }
@@ -195,6 +203,10 @@ let rec stringifyDocItem ?(indentation = 0) ~originalEnv (item : docItem) =
           match m.deprecated with
           | Some d -> Some (wrapInQuotes d)
           | None -> None );
+        ( "moduletypeid",
+          match m.moduletypeid with
+          | Some path -> Some (wrapInQuotes path)
+          | None -> None );
         ("docstrings", Some (stringifyDocstrings m.docstring));
         ( "source",
           Some (stringifySource ~indentation:(indentation + 1) m.source) );
@@ -356,6 +368,7 @@ let extractDocs ~entryPointFile ~debug =
             id = modulePath |> List.rev |> ident;
             docstring = structure.docstring |> List.map String.trim;
             name = structure.name;
+            moduletypeid = None;
             deprecated = structure.deprecated;
             source =
               {
@@ -439,6 +452,7 @@ let extractDocs ~entryPointFile ~debug =
                             {
                               id = modulePath |> List.rev |> ident;
                               name = m.name;
+                              moduletypeid = None;
                               docstring = item.docstring @ m.docstring;
                               deprecated = item.deprecated;
                               source;
@@ -469,12 +483,33 @@ let extractDocs ~entryPointFile ~debug =
                             (extractDocsForModule
                                ~modulePath:(interface.name :: modulePath)
                                interface))
-                     | Module {type_ = Constraint (Structure m, Ident _)} ->
-                       (* module M: T = {  }. Print M *)
+                     | Module {type_ = Constraint (Structure m, Ident p)} ->
+                       (* module M: T = { <impl> }. Print M *)
+                       let docs =
+                         extractDocsForModule ~modulePath:(m.name :: modulePath)
+                           m
+                       in
+                       let identModulePath = p |> Path.head |> Ident.name in
+
+                       let moduleTypeIdPath =
+                         match
+                           ProcessCmt.fileForModule ~package:full.package
+                             identModulePath
+                           |> Option.is_none
+                         with
+                         | false -> []
+                         | true -> [modulePath |> List.rev |> List.hd]
+                       in
+
                        Some
                          (Module
-                            (extractDocsForModule
-                               ~modulePath:(m.name :: modulePath) m))
+                            {
+                              docs with
+                              moduletypeid =
+                                Some
+                                  (makeId ~identifier:(Path.name p)
+                                     moduleTypeIdPath);
+                            })
                      | _ -> None);
           }
         in
diff --git a/tools/tests/src/DocExtractionRes.res b/tools/tests/src/DocExtractionRes.res
index 68c3256e6..b9c7f25cf 100644
--- a/tools/tests/src/DocExtractionRes.res
+++ b/tools/tests/src/DocExtractionRes.res
@@ -128,4 +128,18 @@ module M: Example = {
   let f = (x: int) => x
 }
 
+module type MT = {
+  let x: int
+}
+
+module A: MT = {
+  let x = 42
+}
+
+module C = {
+  module D: MT = {
+    let x = 42
+  }
+}
+
 // ^dex
diff --git a/tools/tests/src/expected/DocExtractionRes.res.json b/tools/tests/src/expected/DocExtractionRes.res.json
index 5f46f92db..93a727b3b 100644
--- a/tools/tests/src/expected/DocExtractionRes.res.json
+++ b/tools/tests/src/expected/DocExtractionRes.res.json
@@ -311,6 +311,7 @@
     "id": "DocExtractionRes.M",
     "name": "M",
     "kind": "module",
+    "moduletypeid": "DocExtractionRes.Example",
     "docstrings": ["implementation of Example module type"],
     "source": {
       "filepath": "src/DocExtractionRes.res",
@@ -342,5 +343,91 @@
         "col": 7
       }
     }]
+  }, 
+  {
+    "id": "DocExtractionRes.MT",
+    "name": "MT",
+    "kind": "moduleType",
+    "docstrings": [],
+    "source": {
+      "filepath": "src/DocExtractionRes.res",
+      "line": 131,
+      "col": 13
+    },
+    "items": [
+    {
+      "id": "DocExtractionRes.MT.x",
+      "kind": "value",
+      "name": "x",
+      "signature": "let x: int",
+      "docstrings": [],
+      "source": {
+        "filepath": "src/DocExtractionRes.res",
+        "line": 132,
+        "col": 3
+      }
+    }]
+  }, 
+  {
+    "id": "DocExtractionRes.A",
+    "name": "A",
+    "kind": "module",
+    "moduletypeid": "DocExtractionRes.MT",
+    "docstrings": [],
+    "source": {
+      "filepath": "src/DocExtractionRes.res",
+      "line": 1,
+      "col": 1
+    },
+    "items": [
+    {
+      "id": "DocExtractionRes.A.x",
+      "kind": "value",
+      "name": "x",
+      "signature": "let x: int",
+      "docstrings": [],
+      "source": {
+        "filepath": "src/DocExtractionRes.res",
+        "line": 136,
+        "col": 7
+      }
+    }]
+  }, 
+  {
+    "id": "DocExtractionRes.C",
+    "name": "C",
+    "kind": "module",
+    "docstrings": [],
+    "source": {
+      "filepath": "src/DocExtractionRes.res",
+      "line": 139,
+      "col": 8
+    },
+    "items": [
+    {
+      "id": "DocExtractionRes.C.D",
+      "name": "D",
+      "kind": "module",
+      "moduletypeid": "DocExtractionRes.MT",
+      "docstrings": [],
+      "source": {
+        "filepath": "src/DocExtractionRes.res",
+        "line": 1,
+        "col": 1
+      },
+      "items": [
+      {
+        "id": "DocExtractionRes.C.D.x",
+        "kind": "value",
+        "name": "x",
+        "signature": "let x: int",
+        "docstrings": [],
+        "source": {
+          "filepath": "src/DocExtractionRes.res",
+          "line": 141,
+          "col": 9
+        }
+      }]
+    }]
   }]
 }