diff --git a/tools/fidlcat/lib/BUILD.gn b/tools/fidlcat/lib/BUILD.gn
index a5faccdffc7d1bbcd7df484012dfb8b8e1471c2d..32d907ec9c2d7281ed563957f53403878996ba8c 100644
--- a/tools/fidlcat/lib/BUILD.gn
+++ b/tools/fidlcat/lib/BUILD.gn
@@ -89,6 +89,8 @@ source_set("tests") {
 action("json_for_test") {
   deps = [
     ":fidl($fidl_toolchain)",
+    ":fidl-sys($fidl_toolchain)",
+    "//sdk/fidl/fuchsia.sys",
     "//sdk/lib/fidl/cpp/test:frobinator",
     "//zircon/public/fidl/fuchsia-io",
   ]
@@ -104,6 +106,8 @@ action("json_for_test") {
         "/fidling/gen/zircon/public/fidl/fuchsia-io/fuchsia-io.fidl.json",
     rebase_path(root_build_dir) +
         "/fidling/gen/tools/fidlcat/lib/fidl.fidl.json",
+    rebase_path(root_build_dir) +
+        "/fidling/gen/tools/fidlcat/lib/fidl-sys.fidl.json",
   ]
 }
 
@@ -115,3 +119,11 @@ fidl("fidl") {
     "testdata/types.test.fidl",
   ]
 }
+
+fidl("fidl-sys") {
+  name = "test.fidlcat.sys"
+
+  sources = [
+    "testdata/sys.test.fidl",
+  ]
+}
diff --git a/tools/fidlcat/lib/generate_test_includes.sh b/tools/fidlcat/lib/generate_test_includes.sh
index 3081f57bcd9f4c07cf2ad2773c9ac1010a72cd74..9e5ed7712f231072ad35f7f823335cc528773dd7 100755
--- a/tools/fidlcat/lib/generate_test_includes.sh
+++ b/tools/fidlcat/lib/generate_test_includes.sh
@@ -25,11 +25,17 @@ class ExampleMap {
   ExampleMap() {
     map_ = {
 EOF
-for i in "$@"; do \
+
+for i in "$@"; do
+  if [[ ! -f "${i}" ]]; then
+     echo "file ${i} not found"
+     exit 1
+  fi;
   cat >> "${FILENAME}" << EOF
     {"${i}", R"FIDL($(cat "${i}"))FIDL"},
 EOF
 done
+
 cat >> "${FILENAME}" << EOF
     };
   }
diff --git a/tools/fidlcat/lib/library_loader.cc b/tools/fidlcat/lib/library_loader.cc
index 2da97a45d8492e50238d0b01257ab4d3473ba7d0..cf0b6dd54c93fd77241dd18924bfa8b7be68f45d 100644
--- a/tools/fidlcat/lib/library_loader.cc
+++ b/tools/fidlcat/lib/library_loader.cc
@@ -51,6 +51,17 @@ std::unique_ptr<Type> Library::TypeFromIdentifier(
   return Type::get_illegal();
 }
 
+bool Library::GetInterfaceByName(const std::string& name,
+                                 const Interface** ptr) const {
+  for (const auto& interface : interfaces()) {
+    if (interface.name() == name) {
+      *ptr = &interface;
+      return true;
+    }
+  }
+  return false;
+}
+
 const std::unique_ptr<Type> Enum::GetType() const {
   // TODO Consider caching this.
   return Type::ScalarTypeFromName(value_["type"].GetString());
@@ -145,7 +156,9 @@ InterfaceMethod::InterfaceMethod(const Interface& interface,
   if (value_["has_request"].GetBool()) {
     request_params_ =
         std::make_optional<std::vector<InterfaceMethodParameter>>();
-    for (auto& request : value["maybe_request"].GetArray()) {
+    auto request_arr = value["maybe_request"].GetArray();
+    request_params_->reserve(request_arr.Size());
+    for (auto& request : request_arr) {
       request_params_->emplace_back(*this, request);
     }
   } else {
@@ -155,7 +168,9 @@ InterfaceMethod::InterfaceMethod(const Interface& interface,
   if (value_["has_response"].GetBool()) {
     response_params_ =
         std::make_optional<std::vector<InterfaceMethodParameter>>();
-    for (auto& response : value["maybe_response"].GetArray()) {
+    auto response_arr = value["maybe_response"].GetArray();
+    response_params_->reserve(response_arr.Size());
+    for (auto& response : response_arr) {
       response_params_->emplace_back(*this, response);
     }
   } else {
@@ -190,4 +205,15 @@ std::string InterfaceMethod::fully_qualified_name() const {
   return enclosing_interface_.name() + "." + name();
 }
 
+bool Interface::GetMethodByFullName(const std::string& name,
+                                    const InterfaceMethod** method_ptr) const {
+  for (const auto& method : methods()) {
+    if (method.fully_qualified_name() == name) {
+      *method_ptr = &method;
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace fidlcat
diff --git a/tools/fidlcat/lib/library_loader.h b/tools/fidlcat/lib/library_loader.h
index cbcc41fafd05dc5c71e164deb1aacc6e9d6d48ed..75f95b0c53f1b2fcd356fe6addc8d16e84c3bc08 100644
--- a/tools/fidlcat/lib/library_loader.h
+++ b/tools/fidlcat/lib/library_loader.h
@@ -89,10 +89,11 @@ class InterfaceMethodParameter {
 
 class InterfaceMethod {
  public:
+  friend class Interface;
   InterfaceMethod(const Interface& interface, const rapidjson::Value& value);
   InterfaceMethod(InterfaceMethod&& other);
 
-  int32_t get_ordinal() const {
+  Ordinal get_ordinal() const {
     return std::strtoll(value_["ordinal"].GetString(), nullptr, 10);
   }
 
@@ -139,6 +140,16 @@ class Interface {
     }
   }
 
+  Interface(Interface&& other)
+      : value_(other.value_), enclosing_library_(other.enclosing_library_) {
+    for (auto& method : other.interface_methods_) {
+      interface_methods_.emplace_back(*this, method.value_);
+    }
+  }
+
+  Interface(const Interface& other) = delete;
+  Interface& operator=(const Interface&) = delete;
+
   std::string name() const { return value_["name"].GetString(); }
 
   void AddMethodsToIndex(std::map<Ordinal, const InterfaceMethod*>& index) {
@@ -149,6 +160,10 @@ class Interface {
     }
   }
 
+  // Sets *|method| to the fully qualified |name|'s InterfaceMethod
+  bool GetMethodByFullName(const std::string& name,
+                           const InterfaceMethod** method) const;
+
   const Library& enclosing_library() const { return enclosing_library_; }
 
   const std::vector<InterfaceMethod>& methods() const {
@@ -224,7 +239,9 @@ class Union {
       : enclosing_library_(enclosing_library),
         value_(value),
         illegal_(nullptr) {
-    for (auto& member : value["members"].GetArray()) {
+    auto member_arr = value["members"].GetArray();
+    members_.reserve(member_arr.Size());
+    for (auto& member : member_arr) {
       members_.emplace_back(*this, member);
     }
   }
@@ -286,7 +303,9 @@ class Struct {
  public:
   Struct(const Library& enclosing_library, const rapidjson::Value& value)
       : enclosing_library_(enclosing_library), value_(value) {
-    for (auto& member : value["members"].GetArray()) {
+    auto member_arr = value["members"].GetArray();
+    members_.reserve(member_arr.Size());
+    for (auto& member : member_arr) {
       members_.emplace_back(*this, member);
     }
   }
@@ -311,7 +330,11 @@ class Library {
  public:
   Library(const LibraryLoader& enclosing, rapidjson::Document& document)
       : enclosing_loader_(enclosing), backing_document_(std::move(document)) {
-    for (auto& decl : backing_document_["interface_declarations"].GetArray()) {
+    auto interfaces_array =
+        backing_document_["interface_declarations"].GetArray();
+    interfaces_.reserve(interfaces_array.Size());
+
+    for (auto& decl : interfaces_array) {
       interfaces_.emplace_back(*this, decl);
     }
     for (auto& enu : backing_document_["enum_declarations"].GetArray()) {
@@ -352,6 +375,9 @@ class Library {
 
   const std::vector<Interface>& interfaces() const { return interfaces_; }
 
+  // Set *ptr to the Interface called |name|
+  bool GetInterfaceByName(const std::string& name, const Interface** ptr) const;
+
   Library& operator=(const Library&) = delete;
   Library(const Library&) = delete;
 
diff --git a/tools/fidlcat/lib/library_loader_test.cc b/tools/fidlcat/lib/library_loader_test.cc
index 50e09e259c5b7286cb2dfce8e61141652caa189e..6fd0060571056c135dd2928ad5a6e4f33044631e 100644
--- a/tools/fidlcat/lib/library_loader_test.cc
+++ b/tools/fidlcat/lib/library_loader_test.cc
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "library_loader.h"
+
 #include <iostream>
 #include <sstream>
 #include <string>
 #include <vector>
 
 #include "gtest/gtest.h"
-#include "library_loader.h"
 #include "tools/fidlcat/lib/library_loader_test_data.h"
 
 namespace fidlcat {
@@ -28,29 +29,54 @@ TEST(LibraryLoader, LoadSimple) {
 
   const Library* library_ptr;
   loader.GetLibraryFromName("fidl.test.frobinator", &library_ptr);
-  const std::vector<Interface>& interfaces = library_ptr->interfaces();
 
   std::string kDesiredInterfaceName = "fidl.test.frobinator/Frobinator";
   const Interface* found_interface = nullptr;
-  for (const auto& interface : interfaces) {
-    if (interface.name() == kDesiredInterfaceName) {
-      found_interface = &interface;
-      break;
-    }
-  }
+  ASSERT_TRUE(
+      library_ptr->GetInterfaceByName(kDesiredInterfaceName, &found_interface));
+
   ASSERT_NE(found_interface, nullptr)
       << "Could not find interface " << kDesiredInterfaceName;
 
-  const InterfaceMethod* found_method = nullptr;
   std::string kDesiredFullMethodName = "fidl.test.frobinator/Frobinator.Frob";
-  for (const auto& method : found_interface->methods()) {
-    if (method.fully_qualified_name() == kDesiredFullMethodName) {
-      found_method = &method;
-      break;
-    }
-  }
+  const InterfaceMethod* found_method = nullptr;
+  found_interface->GetMethodByFullName(kDesiredFullMethodName, &found_method);
+
   ASSERT_NE(found_method, nullptr)
       << "Could not find method " << kDesiredFullMethodName;
 }
 
+TEST(LibraryLoader, LoadFromOrdinal) {
+  fidlcat_test::ExampleMap examples;
+  std::vector<std::unique_ptr<std::istream>> library_files;
+  for (auto element : examples.map()) {
+    std::unique_ptr<std::istream> file = std::make_unique<std::istringstream>(
+        std::istringstream(element.second));
+
+    library_files.push_back(std::move(file));
+  }
+  LibraryReadError err;
+  LibraryLoader loader = LibraryLoader(library_files, &err);
+  ASSERT_EQ(LibraryReadError::kOk, err.value);
+
+  const Library* library_ptr = nullptr;
+  ASSERT_TRUE(loader.GetLibraryFromName("test.fidlcat.sys", &library_ptr));
+
+  std::string kDesiredInterfaceName = "test.fidlcat.sys/ComponentController";
+  const Interface* found_interface = nullptr;
+  ASSERT_TRUE(
+      library_ptr->GetInterfaceByName(kDesiredInterfaceName, &found_interface));
+
+  const InterfaceMethod* found_method = nullptr;
+  found_interface->GetMethodByFullName(
+      "test.fidlcat.sys/ComponentController.OnDirectoryReady", &found_method);
+
+  Ordinal correct_ordinal = found_method->get_ordinal();
+  const InterfaceMethod* ordinal_method;
+  ASSERT_TRUE(loader.GetByOrdinal(correct_ordinal, &ordinal_method));
+  ASSERT_STREQ(kDesiredInterfaceName.c_str(),
+               ordinal_method->enclosing_interface().name().c_str());
+  ASSERT_STREQ("OnDirectoryReady", ordinal_method->name().c_str());
+}
+
 }  // namespace fidlcat
diff --git a/tools/fidlcat/lib/testdata/sys.test.fidl b/tools/fidlcat/lib/testdata/sys.test.fidl
new file mode 100644
index 0000000000000000000000000000000000000000..3e7957559190b4bc7319292383ec0ec25fb422ee
--- /dev/null
+++ b/tools/fidlcat/lib/testdata/sys.test.fidl
@@ -0,0 +1,380 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library test.fidlcat.sys;
+
+// The goal of this file is to get a pretty big library.  It's a copy
+// of fuchsia.sys and fuchsia.mem as of 26 April 2019.
+
+/// A Buffer for data whose size is not necessarily a multiple of the page
+/// size.
+///
+/// VMO objects have a physical size that is always a multiple of the page
+/// size. As such, VMO alone cannot serve as a buffer for arbitrarly sized
+/// data. |fuchsia.mem.Buffer| is a standard struct that aggregate the VMO
+/// and its size.
+struct Buffer {
+    /// The vmo.
+    handle<vmo> vmo;
+
+    /// The size of the data in the vmo in bytes. This size must be smaller
+    /// than the physical size of the vmo.
+    uint64 size;
+};
+
+enum TerminationReason {
+    // The channel closed without giving a termination reason.
+    UNKNOWN = 0;
+    // Component ran and exited with a given return_code.
+    EXITED = 1;
+    // The given URL given to launch was invalid.
+    URL_INVALID = 2;
+    // The requested package could not be found.
+    PACKAGE_NOT_FOUND = 3;
+    // An internal error happened during the launch process.
+    INTERNAL_ERROR = 4;
+    // Process creation failed.
+    PROCESS_CREATION_ERROR = 5;
+    // A Runner failed to start.
+    RUNNER_FAILED = 6;
+    // A Runner terminated while attempting to run a component.
+    RUNNER_TERMINATED = 7;
+    // Attempted to use an unsupported feature.
+    UNSUPPORTED = 8;
+};
+
+// An interface for controlling components.
+//
+// Closing this interface implicitly kills the controlled component unless
+// the |Detach| method has been called.
+//
+// If the component exits, this interface will be closed.
+//
+// Typically obtained via |Launcher.CreateComponent|.
+protocol ComponentController {
+    // Terminates the component.
+    //
+    // This ComponentController connection is closed when the component has
+    // terminated.
+    Kill();
+
+    // Decouples the lifetime of the component from this controller.
+    //
+    // After calling |Detach|, the component will not be implicitly killed when
+    // this interface is closed.
+    Detach();
+
+    // DEPRECATED: Use OnTerminated instead of Wait().
+    // 3: Wait()
+
+    // Event that is triggered when the component is terminated.
+    //
+    // This event provides the return code of the process and reason for
+    // its termination. The return_code is only valid if the termination
+    // reason is EXITED. If the termination reason is not EXITED, the
+    // return code is guaranteed not to be 0.
+    -> OnTerminated(int64 return_code, TerminationReason termination_reason);
+
+    // Event that is triggered when the component's output directory is mounted.
+    //
+    // This event will not be triggered for every component, only those that
+    // serve a directory over their PA_DIRECTORY_REQUEST handle.
+    -> OnDirectoryReady();
+};
+
+// An interface for controlling an environment.
+//
+// Closing this interface implicitly kills the controlled environment unless
+// the |Detach| method has been called.
+//
+// If the environment is destroyed, this interface will be closed.
+//
+// Typically obtained via |Environment.CreateNestedEnvironment|.
+protocol EnvironmentController {
+    // Terminates the environment.
+    //
+    // When an |Environment| is terminated, all applications launched
+    // in the environment (and in all transitively nested environments) are also
+    // killed.
+    Kill() -> ();
+
+    // Decouples the lifetime of the environment from this controller.
+    //
+    // After calling |Detach|, the environment will not be implicitly killed when
+    // this interface is closed.
+    Detach();
+
+    // Event that is triggered when the environment is created.
+    -> OnCreated();
+};
+
+// Maximum length for an environment label.
+const uint32 kLabelMaxLength = 32;
+
+struct EnvironmentOptions {
+    // True if this environment should inherit services provided by the
+    // parent environment.
+    bool inherit_parent_services;
+    // True if components in this environment can share a runner provided
+    // by the parent environment. If false, a new runner will be started
+    // in this environment for components.
+    bool allow_parent_runners;
+    // True if this environment should be killed first in out of memory
+    // situations by setting the ZX_PROP_JOB_KILL_ON_OOM property on this
+    // environment's job.
+    bool kill_on_oom;
+    // True if "persistent" storage requested by components in this environment should not actually
+    // be persistent, and instead be deleted when this environment is killed.
+    bool delete_storage_on_death;
+};
+
+// An interface for managing a set of applications.
+//
+// Applications run inside environments, which provide ambient services and
+// support for their lifecycle.
+[Discoverable]
+protocol Environment {
+    // Creates a new environment nested inside this environment.
+    //
+    // When applications are created inside the nested environment using the
+    // environment's |Launcher|, the environment requests the
+    // environment services from |host_directory| before passing those services to
+    // the newly created application in its |StartupInfo|.
+    //
+    // The |controller| can be used to control the lifecycle of the created
+    // environment. Note that by default the environment will be killed
+    // automatically when the |EnvironmentController|'s interface is closed. You
+    // can use |EnvironmentController.Detach| to disable this behavior.
+    //
+    // |label| defines the new environment's label/name. It must be unique within
+    // the parent environment (though not globally) and is used for isolating
+    // separate environments. It can also be used for diagnostic purposes. The
+    // label will be truncated if it is longer than |kLabelMaxLength|.
+    //
+    // |additional_services|, which may be empty, contains a list of services
+    // that the environment provides, which are hosted by
+    // |additional_services.host_directory|. If |options.inherit_parent_services|
+    // is false, |host_directory| must provide a |Loader| service if it wishes to
+    // allow new components to be loaded in the new environment.
+    //
+    // |options| provides additional options, see |EnvironmentOptions| for
+    // details.
+    CreateNestedEnvironment(request<Environment> environment,
+                            request<EnvironmentController> controller,
+                            string label,
+                            ServiceList? additional_services,
+                            EnvironmentOptions options);
+
+    // Gets the Launcher associated with this environment.
+    //
+    // Applications created using this application launcher will be given the
+    // environment services provided by this environment's |host_directory|.
+    GetLauncher(request<Launcher> launcher);
+
+    // Gets a superset of services provided by this environment's
+    // |host_directory|.
+    GetServices(request<ServiceProvider> services);
+
+    // Gets a superset of services provided by this environment's
+    // |host_directory|.
+    GetDirectory(handle<channel> directory_request);
+};
+
+struct FlatNamespace {
+  // The mount point for each of the directories below.
+  //
+  // For example, ["/pkg", "/svc"].
+  vector<string> paths;
+
+  // The directories mounted at each path in the namespace.
+  vector<handle<channel>> directories;
+};
+
+// An interface for providing a job handle. Instances of this interface are
+// created in the context of an already-identified realm, so there is no need
+// to explicitly identify the realm below.
+[Discoverable]
+protocol JobProvider {
+    // Gets the root job associated with the realm.
+    GetJob() -> (handle<job> job);
+};
+
+// An FDIO file descriptor.
+// TODO(abarth): Use the real FDIO declaration once FDIO converts to FIDL2.
+struct FileDescriptor {
+    // The FDIO types of the handle (e.g., FA_FDIO_REMOTE).
+    int32 type0;
+    int32 type1;
+    int32 type2;
+
+    // The handles for the file descriptor (e.g., a channel).
+    handle? handle0;
+    handle? handle1;
+    handle? handle2;
+};
+
+// Information used to create an instance of a component and obtain
+// services from it.
+struct LaunchInfo {
+    // The location from which to retrieve this component.
+    //
+    // This field will probably be replaced with a stronger notion of identity,
+    // such as an unforgeable token. This field is included in this iteration to
+    // ease the transition from the previous component interfaces.
+    string url;
+
+    // The arguments to be provided to the component.
+    vector<string>? arguments;
+
+    // The file descriptor to use for stdout.
+    //
+    // If null, the component will use the default stdout for the environment.
+    FileDescriptor? out;
+
+    // The file descriptor to use for stderr.
+    //
+    // If null, the component will use the default stderr for the environment.
+    FileDescriptor? err;
+
+    // The interface request for a Directory that is passed through to the
+    // component and arrives in the component as its |directory_request|
+    // interface request.
+    handle<channel>? directory_request;
+
+    // A custom namespace that can be appended to the namespace generated by
+    // appmgr and provided to this component.
+    // Adding a mount point at standard paths like 'pkg' or 'svc' will be ignored.
+    // HACK(alhaad): Adding mount points for deprecated default directories like
+    // '/data' will override the default.
+    FlatNamespace? flat_namespace;
+
+    // A list of services to be added to this component's svc namespace. These
+    // services are in addition to those coming from Environment.
+    ServiceList? additional_services;
+};
+
+struct ServiceList {
+    // A list of services that can be requested from |provider|.
+    vector<string> names;
+
+    // A service provider to get the services listed in |names| from.
+    ServiceProvider? provider;
+
+    // A channel to the directory hosting the services in |names|.
+    // TODO(CP-124): Support |host_directory| for CreateComponent and deprecate
+    // |provider|.
+    handle<channel>? host_directory;
+};
+
+// An interface for creating component instances.
+//
+// Typically obtained via |Environment.GetLauncher|.
+[Discoverable]
+protocol Launcher {
+    // Creates a new instance of the component described by |launch_info|.
+    //
+    // The component instance is created in the |Environment|
+    // associated with this |Launcher|. When creating the component,
+    // the environment requests the environment services for this component from
+    // its |EnvironmentHost|.
+    //
+    // The |controller| can be used to control the lifecycle of the created
+    // component instance. If an |ComponentController|'s interface is
+    // requested, the component instance is killed when the interface is closed.
+    CreateComponent(LaunchInfo launch_info,
+                    request<ComponentController>? controller);
+};
+
+// An interface for loading from pacakges.
+[Discoverable]
+protocol Loader {
+    // LoadUrl a package by url.
+    LoadUrl(string url) -> (Package? package);
+};
+
+// Information given to components at startup.
+//
+// For ELF binaries, this information is provided in the initialization message
+// given to libc by fuchsia.process.Launcher.
+struct StartupInfo {
+    // The launch info for the to start.
+    LaunchInfo launch_info;
+
+    // The namespace in which to run the component.
+    FlatNamespace flat_namespace;
+
+    // Key string value string map of the component's program metadata, obtained
+    // from its component manifest.
+    vector<ProgramMetadata>? program_metadata;
+
+    // TODO(abarth): Add more fields to this struct relating to component and
+    // environment identity.
+};
+
+// Program information about a component.
+struct ProgramMetadata {
+    // Key for program metadata pair. E.g. "binary" for an ELF binary component,
+    // or "data" for a flutter/dart component.
+    string key;
+
+    // Value for program metadata pair. E.g. "bin/app" for a "binary" key, or
+    // "data/foo" for a flutter/dart component.
+    string value;
+};
+
+// A binary representation of a component.
+//
+// Typically provided to |Runner.StartComponent| when starting a
+// component.
+struct Package {
+    // A read-only binary representation of the component. For example, if the
+    // component is intended to run in the Dart virtual machine, this data might
+    // contain a dartx package.
+    Buffer? data;
+
+    // A directory containing the contents of the package. For example, if the
+    // component is stored in pkgfs, this directory will be the pkgfs directory
+    // containing the package.
+    handle<channel>? directory;
+
+    // Resolved URL of the component. This is the url specified in startup_info
+    // after following redirects and resolving relative paths.
+    string resolved_url;
+};
+
+// An interface for running components.
+//
+// Typically exposed by components that provide execution environments for
+// particular classes of programs. For example, the Dart virtual machine exposes
+// this interface to run Dart programs.
+[Discoverable]
+protocol Runner {
+    // Execute the given component.
+    //
+    // Upon startup, the component is to be given the information in
+    // |startup_info|, but the mechanism by which the component receives that
+    // information is up to the component runner.
+    //
+    // The |controller| interface request typically originates from the
+    // |Launcher.CreateComponent| message that caused this
+    // component to be started.
+    StartComponent(Package package,
+                   StartupInfo startup_info,
+                   request<ComponentController>? controller);
+};
+
+// An interface through which a client may request services from a host.
+// Instances of this interface are created within the context of an
+// already-identified client and host pair, so there is no need to explicitly
+// identify the client or host in the methods below.
+//
+// This interface is deprecated.  Services should be published as directory
+// entries instead, just like files.
+// TODO(ZX-1358): Point to the FIDL interface for file I/O once RIO is migrated.
+protocol ServiceProvider {
+    // Asks the host to provide the service identified by |service_name| through
+    // the |channel| endpoint supplied by the caller. If the host is not willing
+    // or able to provide the requested service, it should close the |channel|.
+    ConnectToService(string service_name, handle<channel> channel);
+};