diff --git a/misc/generate_changelog.py b/misc/generate_changelog.py
index 7c7f28b6eeb7..ebab6c569152 100644
--- a/misc/generate_changelog.py
+++ b/misc/generate_changelog.py
@@ -79,7 +79,6 @@ def filter_omitted_commits(commits: list[CommitInfo]) -> list[CommitInfo]:
                 "Revert sum literal integer change",
                 "Remove use of LiteralString in builtins",
                 "Revert typeshed ctypes change",
-                "Revert use of `ParamSpec` for `functools.wraps`",
             )
         ):
             # These are generated by a typeshed sync.
diff --git a/misc/sync-typeshed.py b/misc/sync-typeshed.py
index ee6414ab7b19..56bc1624d5d0 100644
--- a/misc/sync-typeshed.py
+++ b/misc/sync-typeshed.py
@@ -182,7 +182,6 @@ def main() -> None:
         "d25e4a9eb",  # LiteralString reverts
         "d132999ba",  # sum reverts
         "dd12a2d81",  # ctypes reverts
-        "0dd4b6f75",  # ParamSpec for functools.wraps
     ]
     for commit in commits_to_cherry_pick:
         try:
diff --git a/mypy/typeshed/stdlib/functools.pyi b/mypy/typeshed/stdlib/functools.pyi
index 991182486113..d3f702bcef4f 100644
--- a/mypy/typeshed/stdlib/functools.pyi
+++ b/mypy/typeshed/stdlib/functools.pyi
@@ -1,9 +1,9 @@
 import sys
 import types
-from _typeshed import IdentityFunction, SupportsAllComparisons, SupportsItems
+from _typeshed import SupportsAllComparisons, SupportsItems
 from collections.abc import Callable, Hashable, Iterable, Sequence, Sized
 from typing import Any, Generic, Literal, NamedTuple, TypedDict, TypeVar, final, overload
-from typing_extensions import Self, TypeAlias
+from typing_extensions import ParamSpec, Self, TypeAlias
 
 if sys.version_info >= (3, 9):
     from types import GenericAlias
@@ -27,11 +27,13 @@ __all__ = [
 if sys.version_info >= (3, 9):
     __all__ += ["cache"]
 
-_AnyCallable: TypeAlias = Callable[..., object]
-
 _T = TypeVar("_T")
 _T_co = TypeVar("_T_co", covariant=True)
 _S = TypeVar("_S")
+_PWrapped = ParamSpec("_PWrapped")
+_RWrapped = TypeVar("_RWrapped")
+_PWrapper = ParamSpec("_PWrapper")
+_RWrapper = TypeVar("_RWrapper")
 
 @overload
 def reduce(__function: Callable[[_T, _S], _T], __sequence: Iterable[_S], __initial: _T) -> _T: ...
@@ -81,31 +83,41 @@ else:
     ]
 WRAPPER_UPDATES: tuple[Literal["__dict__"]]
 
+class _Wrapped(Generic[_PWrapped, _RWrapped, _PWrapper, _RWrapper]):
+    __wrapped__: Callable[_PWrapped, _RWrapped]
+    def __call__(self, *args: _PWrapper.args, **kwargs: _PWrapper.kwargs) -> _RWrapper: ...
+    # as with ``Callable``, we'll assume that these attributes exist
+    __name__: str
+    __qualname__: str
+
+class _Wrapper(Generic[_PWrapped, _RWrapped]):
+    def __call__(self, f: Callable[_PWrapper, _RWrapper]) -> _Wrapped[_PWrapped, _RWrapped, _PWrapper, _RWrapper]: ...
+
 if sys.version_info >= (3, 12):
     def update_wrapper(
-        wrapper: _T,
-        wrapped: _AnyCallable,
+        wrapper: Callable[_PWrapper, _RWrapper],
+        wrapped: Callable[_PWrapped, _RWrapped],
         assigned: Sequence[str] = ("__module__", "__name__", "__qualname__", "__doc__", "__annotations__", "__type_params__"),
         updated: Sequence[str] = ("__dict__",),
-    ) -> _T: ...
+    ) -> _Wrapped[_PWrapped, _RWrapped, _PWrapper, _RWrapper]: ...
     def wraps(
-        wrapped: _AnyCallable,
+        wrapped: Callable[_PWrapped, _RWrapped],
         assigned: Sequence[str] = ("__module__", "__name__", "__qualname__", "__doc__", "__annotations__", "__type_params__"),
         updated: Sequence[str] = ("__dict__",),
-    ) -> IdentityFunction: ...
+    ) -> _Wrapper[_PWrapped, _RWrapped]: ...
 
 else:
     def update_wrapper(
-        wrapper: _T,
-        wrapped: _AnyCallable,
+        wrapper: Callable[_PWrapper, _RWrapper],
+        wrapped: Callable[_PWrapped, _RWrapped],
         assigned: Sequence[str] = ("__module__", "__name__", "__qualname__", "__doc__", "__annotations__"),
         updated: Sequence[str] = ("__dict__",),
-    ) -> _T: ...
+    ) -> _Wrapped[_PWrapped, _RWrapped, _PWrapper, _RWrapper]: ...
     def wraps(
-        wrapped: _AnyCallable,
+        wrapped: Callable[_PWrapped, _RWrapped],
         assigned: Sequence[str] = ("__module__", "__name__", "__qualname__", "__doc__", "__annotations__"),
         updated: Sequence[str] = ("__dict__",),
-    ) -> IdentityFunction: ...
+    ) -> _Wrapper[_PWrapped, _RWrapped]: ...
 
 def total_ordering(cls: type[_T]) -> type[_T]: ...
 def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsAllComparisons]: ...