diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef953bb9..c91b1e81 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,8 +3,11 @@
 ## Unreleased
 
 ### Added
+- Relax requirements for `withDefault` and `view`. Now they could be used with `MutableMetaProvider`
+- Add `MutableMetaProvider` to `MutableMeta` converter `asMutableMeta`.
 
 ### Changed
+- Implementation of `Meta::withDefault`
 
 ### Deprecated
 
diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt
index fd953085..bb9b90f6 100644
--- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt
@@ -249,11 +249,26 @@ public inline fun <reified E : Enum<E>> Meta?.enum(): E? = this?.value?.let {
 public val Meta?.stringList: List<String>? get() = this?.value?.list?.map { it.string }
 
 /**
- * Create a provider that uses given provider for default values if those are not found in this provider
+ * Create a provider that uses a given provider for default values if those are not found in this provider
  */
-public fun Meta.withDefault(default: MetaProvider?): Meta = if (default == null) {
+public fun MetaProvider.withDefault(default: MetaProvider?): Meta = if (default == null && this is Meta) {
     this
 } else {
-    //TODO optimize
-    toMutableMeta().withDefault(default)
+    object : Meta {
+        override val value: Value?
+            get() = this@withDefault.getValue(Name.EMPTY) ?: default?.getValue(Name.EMPTY)
+
+        override val items: Map<NameToken, Meta>
+            get() = buildMap {
+                default?.get(Name.EMPTY)?.items?.let { putAll(it) }
+                this@withDefault.get(Name.EMPTY)?.items?.let { putAll(it) }
+            }
+
+        override fun toString(): String = Meta.toString(this)
+
+        override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta)
+
+        override fun hashCode(): Int = Meta.hashCode(this)
+
+    }
 }
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt
index a11a5a53..f1084692 100644
--- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt
+++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt
@@ -37,7 +37,7 @@ public interface MutableMeta : Meta, MutableMetaProvider {
     override val items: Map<NameToken, MutableMeta>
 
     /**
-     * Get or set value of this node
+     * Get or set the value of this node
      */
     override var value: Value?
 
@@ -437,7 +437,7 @@ public inline fun Meta.copy(modification: MutableMeta.() -> Unit = {}): Meta = M
 }
 
 private class MutableMetaWithDefault(
-    val source: MutableMeta, val default: MetaProvider, val rootName: Name,
+    val source: MutableMetaProvider, val default: MetaProvider, val rootName: Name,
 ) : MutableMeta {
     override val items: Map<NameToken, MutableMeta>
         get() {
@@ -474,9 +474,20 @@ private class MutableMetaWithDefault(
 }
 
 /**
- * Create a mutable item provider that uses given provider for default values if those are not found in this provider.
+ * Create a mutable item provider that uses a given provider for default values if those are not found in this provider.
  * Changes are propagated only to this provider.
  */
-public fun MutableMeta.withDefault(default: MetaProvider?): MutableMeta = if (default == null) {
-    this
-} else MutableMetaWithDefault(this, default, Name.EMPTY)
+public fun MutableMetaProvider.withDefault(
+    default: MetaProvider?
+): MutableMeta = if (default == null) {
+    (this as? MutableMeta) ?: asMutableMeta()
+} else {
+    MutableMetaWithDefault(this, default, Name.EMPTY)
+}
+
+/**
+ * Use multiple default providers. Providers are queried in order of appearance. The first non-null value is returned
+ */
+public fun MutableMetaProvider.withDefaults(vararg defaults: MetaProvider): MutableMeta = withDefault { name ->
+    defaults.firstNotNullOfOrNull { it[name] }
+}
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaView.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaView.kt
index 2bc3f9aa..81a87ef9 100644
--- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaView.kt
+++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaView.kt
@@ -9,7 +9,7 @@ import space.kscience.dataforge.names.plus
  * A [Meta] child proxy that creates required nodes on value write
  */
 private class MutableMetaView(
-    val origin: MutableMeta,
+    val origin: MutableMetaProvider,
     val path: Name
 ) : MutableMeta {
 
@@ -42,6 +42,11 @@ private class MutableMetaView(
  * The difference between this method and regular [getOrCreate] is that [getOrCreate] always creates and attaches node
  * even if it is empty.
  */
-public fun MutableMeta.view(name: Name): MutableMeta = MutableMetaView(this, name)
+public fun MutableMetaProvider.view(name: Name): MutableMeta = MutableMetaView(this, name)
 
-public fun MutableMeta.view(name: String): MutableMeta = view(name.parseAsName())
\ No newline at end of file
+public fun MutableMetaProvider.view(name: String): MutableMeta = view(name.parseAsName())
+
+/**
+ * Create a view of root node, thus effectively representing [MutableMetaProvider] as [MutableMeta]
+ */
+public fun MutableMetaProvider.asMutableMeta(): MutableMeta = view(Name.EMPTY)
\ No newline at end of file
diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/valueExtensions.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/valueExtensions.kt
index 0c87bcc2..e84d7da0 100644
--- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/valueExtensions.kt
+++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/valueExtensions.kt
@@ -6,7 +6,7 @@ package space.kscience.dataforge.meta
 public fun Value.isNull(): Boolean = this == Null
 
 /**
- * Check if value is list.
+ * Check if the value is a list.
  */
 public fun Value.isList(): Boolean = this.type == ValueType.LIST