[fidlgen][llcpp] Move protocol name out of the marker

This adds a function fidl::DiscoverableProtocolName<Protocol> that
returns the name to use and removes Protocol::Name. It also adds a
constexpr function fidl::DiscoverableProtocolDefaultPath<Protocol> that
returns the path under "/svc/" that the given protocol will be exposed
by default.

Bug: 74067

Change-Id: I62ac406b11a3b9bd93d981a83683425e5021d2a5
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/511171
Commit-Queue: Ian McKellar <ianloic@google.com>
Reviewed-by: Yifei Teng <yifeit@google.com>
diff --git a/examples/fidl/llcpp/server/main.cc b/examples/fidl/llcpp/server/main.cc
index d5188ee..f07c929 100644
--- a/examples/fidl/llcpp/server/main.cc
+++ b/examples/fidl/llcpp/server/main.cc
@@ -80,10 +80,11 @@
 
   // Register a handler for components trying to connect to fuchsia.examples.Echo.
   status = outgoing.svc_dir()->AddEntry(
-      fuchsia_examples::Echo::Name,
+      fidl::DiscoverableProtocolName<fuchsia_examples::Echo>,
       fbl::MakeRefCounted<fs::Service>(
           [&server, dispatcher](fidl::ServerEnd<fuchsia_examples::Echo> request) mutable {
-            std::cout << "Incoming connection for " << fuchsia_examples::Echo::Name << std::endl;
+            std::cout << "Incoming connection for "
+                      << fidl::DiscoverableProtocolName<fuchsia_examples::Echo> << std::endl;
             server.Bind(dispatcher, std::move(request));
             return ZX_OK;
           }));
diff --git a/sdk/lib/fdio/internal.h b/sdk/lib/fdio/internal.h
index bf01825..2866118 100644
--- a/sdk/lib/fdio/internal.h
+++ b/sdk/lib/fdio/internal.h
@@ -387,8 +387,8 @@
       if (endpoints.is_error()) {
         return endpoints.take_error();
       }
-      zx_status_t status =
-          fdio_service_connect_by_name(T::Name, endpoints->server.channel().release());
+      zx_status_t status = fdio_service_connect_by_name(fidl::DiscoverableProtocolName<T>,
+                                                        endpoints->server.channel().release());
       if (status != ZX_OK) {
         return zx::error(status);
       }
diff --git a/sdk/lib/fdio/spawn.cc b/sdk/lib/fdio/spawn.cc
index 9deef87..b4d2966 100644
--- a/sdk/lib/fdio/spawn.cc
+++ b/sdk/lib/fdio/spawn.cc
@@ -143,7 +143,8 @@
     report_error(err_msg, "failed to create channel for resolver service: %d", status);
     return ZX_ERR_INTERNAL;
   }
-  status = fdio_service_connect_by_name(fprocess::Resolver::Name, request.release());
+  status = fdio_service_connect_by_name(fidl::DiscoverableProtocolName<fprocess::Resolver>,
+                                        request.release());
   if (status != ZX_OK) {
     report_error(err_msg, "failed to connect to resolver service: %d", status);
     return ZX_ERR_INTERNAL;
@@ -762,7 +763,8 @@
     report_error(err_msg, "failed to create channel for launcher service: %d", status);
     goto cleanup;
   }
-  status = fdio_service_connect_by_name(fprocess::Launcher::Name, request.release());
+  status = fdio_service_connect_by_name(fidl::DiscoverableProtocolName<fprocess::Launcher>,
+                                        request.release());
   if (status != ZX_OK) {
     report_error(err_msg, "failed to connect to launcher service: %d", status);
     goto cleanup;
diff --git a/sdk/lib/fdio/tests/fdio_directory.cc b/sdk/lib/fdio/tests/fdio_directory.cc
index 9911a6a..e9078ab 100644
--- a/sdk/lib/fdio/tests/fdio_directory.cc
+++ b/sdk/lib/fdio/tests/fdio_directory.cc
@@ -25,8 +25,8 @@
   ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, fdio_service_connect("/", h2.release()));
 
   ASSERT_OK(zx::channel::create(0, &h1, &h2));
-  std::string path = std::string("/svc/") + fuchsia_process::Launcher::Name;
-  ASSERT_OK(fdio_service_connect(path.c_str(), h1.release()));
+  ASSERT_OK(fdio_service_connect(fidl::DiscoverableProtocolDefaultPath<fuchsia_process::Launcher>,
+                                 h1.release()));
 }
 
 TEST(DirectoryTest, Open) {
@@ -42,8 +42,10 @@
 
   zx::channel h3, h4;
   ASSERT_OK(zx::channel::create(0, &h3, &h4));
-  ASSERT_OK(fdio_service_connect_at(h2.get(), fuchsia_process::Launcher::Name, h3.release()));
-  ASSERT_OK(fdio_open_at(h2.get(), fuchsia_process::Launcher::Name, kReadFlags, h4.release()));
+  ASSERT_OK(fdio_service_connect_at(
+      h2.get(), fidl::DiscoverableProtocolName<fuchsia_process::Launcher>, h3.release()));
+  ASSERT_OK(fdio_open_at(h2.get(), fidl::DiscoverableProtocolName<fuchsia_process::Launcher>,
+                         kReadFlags, h4.release()));
 
   h3.reset(fdio_service_clone(h2.get()));
   ASSERT_TRUE(h3.is_valid());
diff --git a/sdk/lib/fdio/tests/fdio_pty.cc b/sdk/lib/fdio/tests/fdio_pty.cc
index 15aad83..7f220df 100644
--- a/sdk/lib/fdio/tests/fdio_pty.cc
+++ b/sdk/lib/fdio/tests/fdio_pty.cc
@@ -18,9 +18,8 @@
 
   auto client = fidl::BindSyncClient(std::move(endpoints->client));
 
-  std::string path = "/svc/";
-  path.append(fpty::Device::Name);
-  ASSERT_OK(fdio_service_connect(path.c_str(), endpoints->server.channel().release()));
+  ASSERT_OK(fdio_service_connect(fidl::DiscoverableProtocolDefaultPath<fpty::Device>,
+                                 endpoints->server.channel().release()));
 
   auto endpoints0 = fidl::CreateEndpoints<fpty::Device>();
   ASSERT_OK(endpoints0.status_value());
diff --git a/src/bringup/bin/console-launcher/virtcon-setup.cc b/src/bringup/bin/console-launcher/virtcon-setup.cc
index 98fbc06..384d1ad 100644
--- a/src/bringup/bin/console-launcher/virtcon-setup.cc
+++ b/src/bringup/bin/console-launcher/virtcon-setup.cc
@@ -146,7 +146,7 @@
     status = fdio_service_connect("/svc/fuchsia.virtualconsole.SessionManager", remote.release());
     if (status != ZX_OK) {
       fprintf(stderr, "console-launcher: unable to connect to %s: %d\n",
-              fuchsia_virtualconsole::SessionManager::Name, status);
+              fidl::DiscoverableProtocolName<fuchsia_virtualconsole::SessionManager>, status);
       return status;
     }
     virtcon = fidl::WireSyncClient<fuchsia_virtualconsole::SessionManager>(std::move(local));
diff --git a/src/bringup/bin/console/main.cc b/src/bringup/bin/console/main.cc
index ee75155..556f2c14 100644
--- a/src/bringup/bin/console/main.cc
+++ b/src/bringup/bin/console/main.cc
@@ -151,7 +151,7 @@
 
   using Vnode =
       fs_pty::TtyService<fs_pty::SimpleConsoleOps<fbl::RefPtr<Console>>, fbl::RefPtr<Console>>;
-  outgoing.svc_dir()->AddEntry(fuchsia_hardware_pty::Device::Name,
+  outgoing.svc_dir()->AddEntry(fidl::DiscoverableProtocolName<fuchsia_hardware_pty::Device>,
                                fbl::AdoptRef(new Vnode(std::move(console))));
 
   status = loop.Run();
diff --git a/src/bringup/bin/device-name-provider/args.cc b/src/bringup/bin/device-name-provider/args.cc
index 9d0db73..345ee91 100644
--- a/src/bringup/bin/device-name-provider/args.cc
+++ b/src/bringup/bin/device-name-provider/args.cc
@@ -50,7 +50,8 @@
     return -1;
   }
 
-  status = fdio_service_connect_at(svc_root.get(), fuchsia_boot::Arguments::Name, remote.release());
+  status = fdio_service_connect_at(
+      svc_root.get(), fidl::DiscoverableProtocolName<fuchsia_boot::Arguments>, remote.release());
   if (status != ZX_OK) {
     *error = "netsvc: unable to connect to fuchsia.boot.Arguments";
     return -1;
diff --git a/src/bringup/bin/device-name-provider/device-name-provider.cc b/src/bringup/bin/device-name-provider/device-name-provider.cc
index 98a6d40..7093fc2 100644
--- a/src/bringup/bin/device-name-provider/device-name-provider.cc
+++ b/src/bringup/bin/device-name-provider/device-name-provider.cc
@@ -151,7 +151,7 @@
   DeviceNameProviderServer server(device_name, strnlen(device_name, sizeof(device_name)));
 
   outgoing.svc_dir()->AddEntry(
-      fuchsia_device::NameProvider::Name,
+      fidl::DiscoverableProtocolName<fuchsia_device::NameProvider>,
       fbl::MakeRefCounted<fs::Service>([dispatcher, server](zx::channel svc_request) mutable {
         zx_status_t status =
             fidl::BindSingleInFlightOnly(dispatcher, std::move(svc_request), &server);
diff --git a/src/bringup/bin/device-name-provider/tests/args-test.cc b/src/bringup/bin/device-name-provider/tests/args-test.cc
index 4f9510b..100f6ea 100644
--- a/src/bringup/bin/device-name-provider/tests/args-test.cc
+++ b/src/bringup/bin/device-name-provider/tests/args-test.cc
@@ -30,7 +30,7 @@
  public:
   explicit FakeSvc(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher), vfs_(dispatcher) {
     auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
-    root_dir->AddEntry(fuchsia_boot::Arguments::Name,
+    root_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_boot::Arguments>,
                        fbl::MakeRefCounted<fs::Service>(
                            [this](fidl::ServerEnd<fuchsia_boot::Arguments> server_end) {
                              fidl::BindServer(dispatcher_, std::move(server_end), &mock_boot_);
diff --git a/src/bringup/bin/device-name-provider/tests/integration-test.cc b/src/bringup/bin/device-name-provider/tests/integration-test.cc
index 3bd94d4..f962f17 100644
--- a/src/bringup/bin/device-name-provider/tests/integration-test.cc
+++ b/src/bringup/bin/device-name-provider/tests/integration-test.cc
@@ -33,7 +33,7 @@
 
   ASSERT_EQ(status = zx::channel::create(0, &c0, &c1), ZX_OK) << zx_status_get_string(status);
   ASSERT_EQ(status = sys::ServiceDirectory::CreateFromNamespace()->Connect(
-                fuchsia_device::NameProvider::Name, std::move(c1)),
+                fidl::DiscoverableProtocolName<fuchsia_device::NameProvider>, std::move(c1)),
             ZX_OK)
       << zx_status_get_string(status);
 
diff --git a/src/bringup/bin/netsvc/BUILD.gn b/src/bringup/bin/netsvc/BUILD.gn
index 6a80636..1815b95 100644
--- a/src/bringup/bin/netsvc/BUILD.gn
+++ b/src/bringup/bin/netsvc/BUILD.gn
@@ -110,6 +110,7 @@
     "//zircon/system/ulib/async-loop:async-loop-default",
     "//zircon/system/ulib/fdio-caller",
     "//zircon/system/ulib/fidl-async:fidl-async-cpp",
+    "//zircon/system/ulib/service:service-llcpp",
     "//zircon/system/ulib/sysconfig-client:sysconfig-sync-client",
     "//zircon/system/ulib/zbitl",
   ]
diff --git a/src/bringup/bin/netsvc/args.cc b/src/bringup/bin/netsvc/args.cc
index 059fb06..e7fafd9 100644
--- a/src/bringup/bin/netsvc/args.cc
+++ b/src/bringup/bin/netsvc/args.cc
@@ -42,7 +42,8 @@
     return -1;
   }
 
-  status = fdio_service_connect_at(svc_root.get(), fuchsia_boot::Arguments::Name, remote.release());
+  status = fdio_service_connect_at(
+      svc_root.get(), fidl::DiscoverableProtocolName<fuchsia_boot::Arguments>, remote.release());
   if (status != ZX_OK) {
     *error = "netsvc: unable to connect to fuchsia.boot.Arguments";
     return -1;
diff --git a/src/bringup/bin/netsvc/netboot.cc b/src/bringup/bin/netsvc/netboot.cc
index 6f29c7e..5239f3e6 100644
--- a/src/bringup/bin/netsvc/netboot.cc
+++ b/src/bringup/bin/netsvc/netboot.cc
@@ -77,7 +77,7 @@
   using Resource = fuchsia_boot::RootResource;
 
   zx::channel local;
-  if (!ConnectToService(Resource::Name, local)) {
+  if (!ConnectToService(fidl::DiscoverableProtocolName<Resource>, local)) {
     return false;
   }
   fidl::WireSyncClient<Resource> client(std::move(local));
@@ -301,7 +301,8 @@
     return ZX_ERR_INTERNAL;
   }
   zx::channel devmgr_channel;
-  if (!ConnectToService(fuchsia_device_manager::Administrator::Name, devmgr_channel)) {
+  if (!ConnectToService(fidl::DiscoverableProtocolName<fuchsia_device_manager::Administrator>,
+                        devmgr_channel)) {
     return ZX_ERR_INTERNAL;
   }
 
@@ -320,7 +321,7 @@
   namespace statecontrol = fuchsia_hardware_power_statecontrol;
 
   zx::channel local;
-  if (!ConnectToService(statecontrol::Admin::Name, local)) {
+  if (!ConnectToService(fidl::DiscoverableProtocolName<statecontrol::Admin>, local)) {
     return ZX_ERR_INTERNAL;
   }
   auto response = fidl::WireCall<statecontrol::Admin>(local.borrow())
diff --git a/src/bringup/bin/netsvc/paver.cc b/src/bringup/bin/netsvc/paver.cc
index f76b475..eee1c4d 100644
--- a/src/bringup/bin/netsvc/paver.cc
+++ b/src/bringup/bin/netsvc/paver.cc
@@ -9,6 +9,7 @@
 #include <lib/async-loop/default.h>
 #include <lib/fdio/directory.h>
 #include <lib/fit/defer.h>
+#include <lib/service/llcpp/service.h>
 #include <lib/sysconfig/sync-client.h>
 #include <lib/zx/clock.h>
 #include <stdio.h>
@@ -658,20 +659,14 @@
   }
   auto buffer_cleanup = fit::defer([this]() { buffer_mapper_.Reset(); });
 
-  zx::channel paver_local, paver_remote;
-  status = zx::channel::create(0, &paver_local, &paver_remote);
-  if (status != ZX_OK) {
-    fprintf(stderr, "netsvc: Unable to create channel pair.\n");
-    return TFTP_ERR_IO;
-  }
-  status =
-      fdio_service_connect_at(svc_root_.get(), fuchsia_paver::Paver::Name, paver_remote.release());
-  if (status != ZX_OK) {
-    fprintf(stderr, "netsvc: Unable to open /svc/%s.\n", fuchsia_paver::Paver::Name);
+  auto paver = service::ConnectAt<fuchsia_paver::Paver>(svc_root_);
+  if (paver.is_error()) {
+    fprintf(stderr, "netsvc: Unable to open /svc/%s.\n",
+            fidl::DiscoverableProtocolName<fuchsia_paver::Paver>);
     return TFTP_ERR_IO;
   }
 
-  paver_svc_.emplace(std::move(paver_local));
+  paver_svc_.emplace(std::move(*paver));
   auto svc_cleanup = fit::defer([&]() { paver_svc_.reset(); });
 
   size_ = size;
diff --git a/src/bringup/bin/netsvc/paver.h b/src/bringup/bin/netsvc/paver.h
index d910a10..cacb110 100644
--- a/src/bringup/bin/netsvc/paver.h
+++ b/src/bringup/bin/netsvc/paver.h
@@ -103,7 +103,7 @@
   Command command_;
 
   // Channel to svc.
-  zx::channel svc_root_;
+  fidl::ClientEnd<fuchsia_io::Directory> svc_root_;
 
   // File descriptor to dev.
   fbl::unique_fd devfs_root_;
diff --git a/src/bringup/bin/netsvc/test/args-test.cc b/src/bringup/bin/netsvc/test/args-test.cc
index ff3b958..fa19452 100644
--- a/src/bringup/bin/netsvc/test/args-test.cc
+++ b/src/bringup/bin/netsvc/test/args-test.cc
@@ -44,7 +44,7 @@
  public:
   explicit FakeSvc(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher), vfs_(dispatcher) {
     auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
-    root_dir->AddEntry(fuchsia_boot::Arguments::Name,
+    root_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_boot::Arguments>,
                        fbl::MakeRefCounted<fs::Service>(
                            [this](fidl::ServerEnd<fuchsia_boot::Arguments> server_end) {
                              fidl::BindServer(dispatcher_, std::move(server_end), &mock_boot_);
diff --git a/src/bringup/bin/netsvc/test/paver-test-common.h b/src/bringup/bin/netsvc/test/paver-test-common.h
index 43dbaa2..a64d3e2 100644
--- a/src/bringup/bin/netsvc/test/paver-test-common.h
+++ b/src/bringup/bin/netsvc/test/paver-test-common.h
@@ -402,10 +402,11 @@
  public:
   explicit FakeSvc(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher), vfs_(dispatcher) {
     auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
-    root_dir->AddEntry(fuchsia_paver::Paver::Name,
-                       fbl::MakeRefCounted<fs::Service>([this](zx::channel request) {
-                         return fake_paver_.Connect(dispatcher_, std::move(request));
-                       }));
+    root_dir->AddEntry(
+        fidl::DiscoverableProtocolName<fuchsia_paver::Paver>,
+        fbl::MakeRefCounted<fs::Service>([this](fidl::ServerEnd<fuchsia_paver::Paver> request) {
+          return fake_paver_.Connect(dispatcher_, request.TakeChannel());
+        }));
 
     zx::channel svc_remote;
     ASSERT_OK(zx::channel::create(0, &svc_local_, &svc_remote));
diff --git a/src/bringup/bin/ptysvc/main.cc b/src/bringup/bin/ptysvc/main.cc
index b9cfebb..4a952d9 100644
--- a/src/bringup/bin/ptysvc/main.cc
+++ b/src/bringup/bin/ptysvc/main.cc
@@ -66,9 +66,10 @@
     printf("console: failed to add svc to root dir: %s\n", zx_status_get_string(status));
     return -1;
   }
-  if ((status = svc_dir->AddEntry(fuchsia_hardware_pty::Device::Name,
+  if ((status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_hardware_pty::Device>,
                                   fbl::MakeRefCounted<PtyGeneratingVnode>(&vfs))) != ZX_OK) {
-    printf("console: failed to add %s to svc dir: %s\n", fuchsia_hardware_pty::Device::Name,
+    printf("console: failed to add %s to svc dir: %s\n",
+           fidl::DiscoverableProtocolName<fuchsia_hardware_pty::Device>,
            zx_status_get_string(status));
     return -1;
   }
diff --git a/src/bringup/bin/pwrbtn-monitor/pwrbtn-monitor.cc b/src/bringup/bin/pwrbtn-monitor/pwrbtn-monitor.cc
index 6873468..e0e7ad7 100644
--- a/src/bringup/bin/pwrbtn-monitor/pwrbtn-monitor.cc
+++ b/src/bringup/bin/pwrbtn-monitor/pwrbtn-monitor.cc
@@ -156,7 +156,8 @@
     return ZX_ERR_INTERNAL;
   }
 
-  auto service = fbl::StringPrintf("/svc/%s", statecontrol_fidl::Admin::Name);
+  auto service =
+      fbl::StringPrintf("/svc/%s", fidl::DiscoverableProtocolName<statecontrol_fidl::Admin>);
   status = fdio_service_connect(service.c_str(), channel_remote.release());
   if (status != ZX_OK) {
     printf("pwrbtn-monitor: failed to connect to service %s: %d\n", service.c_str(), status);
diff --git a/src/bringup/bin/svchost/crashsvc-test.cc b/src/bringup/bin/svchost/crashsvc-test.cc
index e4be763..da06244 100644
--- a/src/bringup/bin/svchost/crashsvc-test.cc
+++ b/src/bringup/bin/svchost/crashsvc-test.cc
@@ -220,7 +220,7 @@
  public:
   FakeService(async_dispatcher_t* dispatcher) : vfs_(dispatcher) {
     auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
-    root_dir->AddEntry(fuchsia_exception::Handler::Name,
+    root_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_exception::Handler>,
                        fbl::MakeRefCounted<fs::Service>([this, dispatcher](zx::channel request) {
                          return exception_handler_.Connect(dispatcher, std::move(request));
                        }));
diff --git a/src/bringup/bin/svchost/exception_handler.cc b/src/bringup/bin/svchost/exception_handler.cc
index b92c5aa..0d34d9e 100644
--- a/src/bringup/bin/svchost/exception_handler.cc
+++ b/src/bringup/bin/svchost/exception_handler.cc
@@ -74,9 +74,9 @@
     return;
   }
 
-  if (const zx_status_t status =
-          fdio_service_connect_at(exception_handler_svc_, fuchsia_exception::Handler::Name,
-                                  server_endpoint_.channel().release());
+  if (const zx_status_t status = fdio_service_connect_at(
+          exception_handler_svc_, fidl::DiscoverableProtocolName<fuchsia_exception::Handler>,
+          server_endpoint_.channel().release());
       status != ZX_OK) {
     LogError("unable to connect to fuchsia.exception.Handler", status);
     drop_exceptions_ = true;
diff --git a/src/bringup/bin/svchost/svchost.cc b/src/bringup/bin/svchost/svchost.cc
index b62250b..6d2f413 100644
--- a/src/bringup/bin/svchost/svchost.cc
+++ b/src/bringup/bin/svchost/svchost.cc
@@ -45,7 +45,8 @@
             zx_status_get_string(status));
     return zx::error(status);
   }
-  status = fdio_service_connect_at(svc_root.get(), fuchsia_kernel::RootJob::Name, remote.release());
+  status = fdio_service_connect_at(
+      svc_root.get(), fidl::DiscoverableProtocolName<fuchsia_kernel::RootJob>, remote.release());
   if (status != ZX_OK) {
     fprintf(stderr, "svchost: unable to connect to fuchsia.kernel.RootJob\n");
     return zx::error(status);
@@ -67,8 +68,8 @@
             zx_status_get_string(status));
     return zx::error(status);
   }
-  status =
-      fdio_service_connect_at(svc_root.get(), fuchsia_boot::RootResource::Name, remote.release());
+  status = fdio_service_connect_at(
+      svc_root.get(), fidl::DiscoverableProtocolName<fuchsia_boot::RootResource>, remote.release());
   if (status != ZX_OK) {
     fprintf(stderr, "svchost: unable to connect to fuchsia.boot.RootResource\n");
     return zx::error(status);
@@ -222,7 +223,8 @@
               zx_status_get_string(status));
       return 1;
     }
-    status = fdio_service_connect_at(caller.channel()->get(), fuchsia_boot::Arguments::Name,
+    status = fdio_service_connect_at(caller.channel()->get(),
+                                     fidl::DiscoverableProtocolName<fuchsia_boot::Arguments>,
                                      remote.release());
     if (status != ZX_OK) {
       fprintf(stderr, "svchost: unable to connect to fuchsia.boot.Arguments");
diff --git a/src/bringup/bin/sysinfo/main.cc b/src/bringup/bin/sysinfo/main.cc
index c762b22..adf7b54 100644
--- a/src/bringup/bin/sysinfo/main.cc
+++ b/src/bringup/bin/sysinfo/main.cc
@@ -35,7 +35,7 @@
     return -1;
   }
   status = outgoing.svc_dir()->AddEntry(
-      fuchsia_sysinfo::SysInfo::Name,
+      fidl::DiscoverableProtocolName<fuchsia_sysinfo::SysInfo>,
       fbl::MakeRefCounted<fs::Service>([dispatcher, sysinfo](zx::channel svc_request) mutable {
         zx_status_t status =
             fidl::BindSingleInFlightOnly(dispatcher, std::move(svc_request), &sysinfo);
diff --git a/src/bringup/bin/sysinfo/sysinfo-test.cc b/src/bringup/bin/sysinfo/sysinfo-test.cc
index e28806b..3a9bb79 100644
--- a/src/bringup/bin/sysinfo/sysinfo-test.cc
+++ b/src/bringup/bin/sysinfo/sysinfo-test.cc
@@ -26,7 +26,7 @@
 
 namespace {
 
-const std::string kSysinfoPath = "/svc/" + std::string(SysInfo::Name);
+const std::string kSysinfoPath = fidl::DiscoverableProtocolDefaultPath<SysInfo>;
 
 }  // namespace
 
diff --git a/src/bringup/bin/virtcon/main.cc b/src/bringup/bin/virtcon/main.cc
index 08af9b3..2314b1e 100644
--- a/src/bringup/bin/virtcon/main.cc
+++ b/src/bringup/bin/virtcon/main.cc
@@ -90,7 +90,7 @@
     return -1;
   }
   status = outgoing.svc_dir()->AddEntry(
-      fuchsia_virtualconsole::SessionManager::Name,
+      fidl::DiscoverableProtocolName<fuchsia_virtualconsole::SessionManager>,
       fbl::MakeRefCounted<fs::Service>(
           [&virtcon_server](
               fidl::ServerEnd<fuchsia_virtualconsole::SessionManager> request) mutable {
diff --git a/src/connectivity/openthread/ot-stack/src/app.cc b/src/connectivity/openthread/ot-stack/src/app.cc
index 763fd28..bfab021 100644
--- a/src/connectivity/openthread/ot-stack/src/app.cc
+++ b/src/connectivity/openthread/ot-stack/src/app.cc
@@ -291,7 +291,7 @@
   bootstrap_impl_ = std::make_unique<ot::Fuchsia::BootstrapThreadImpl>();
 
   status = outgoing_->svc_dir()->AddEntry(
-      fuchsia_lowpan_bootstrap::Thread::Name,
+      fidl::DiscoverableProtocolName<fuchsia_lowpan_bootstrap::Thread>,
       fbl::MakeRefCounted<fs::Service>(
           [this](fidl::ServerEnd<fuchsia_lowpan_bootstrap::Thread> request) {
             zx_status_t status =
@@ -320,7 +320,7 @@
   fidl_request_handler_ptr_ = std::make_unique<LowpanSpinelDeviceFidlImpl>(*this);
 
   status = outgoing_->svc_dir()->AddEntry(
-      fidl_spinel::Device::Name,
+      fidl::DiscoverableProtocolName<fidl_spinel::Device>,
       fbl::MakeRefCounted<fs::Service>([this](fidl::ServerEnd<fidl_spinel::Device> request) {
         if (binding_) {  // TODO (jiamingw) add support for multiple clients
           FX_LOGS(ERROR) << "FIDL connect request rejected: already bound";
diff --git a/src/connectivity/openthread/third_party/openthread/platform/bootstrap_fidl_impl.cc b/src/connectivity/openthread/third_party/openthread/platform/bootstrap_fidl_impl.cc
index 59ff0e8..22e311f 100644
--- a/src/connectivity/openthread/third_party/openthread/platform/bootstrap_fidl_impl.cc
+++ b/src/connectivity/openthread/third_party/openthread/platform/bootstrap_fidl_impl.cc
@@ -54,7 +54,7 @@
 void BootstrapThreadImpl::StopServingFidl() {
   if (svc_dir_) {
     FX_LOGS(INFO) << "Removing svc entry";
-    svc_dir_.value()->RemoveEntry(fuchsia_lowpan_bootstrap::Thread::Name);
+    svc_dir_.value()->RemoveEntry(fidl::DiscoverableProtocolName<fuchsia_lowpan_bootstrap::Thread>);
     svc_dir_.reset();
   }
 }
diff --git a/src/devices/bin/driver-registrar/driver-registrar.cc b/src/devices/bin/driver-registrar/driver-registrar.cc
index 271c264..fdafd5c 100644
--- a/src/devices/bin/driver-registrar/driver-registrar.cc
+++ b/src/devices/bin/driver-registrar/driver-registrar.cc
@@ -23,8 +23,8 @@
     return status;
   }
 
-  const auto svc_path =
-      fbl::StringPrintf("/svc/%s", fuchsia_driver_registrar::DriverRegistrar::Name);
+  const auto svc_path = fbl::StringPrintf(
+      "/svc/%s", fidl::DiscoverableProtocolName<fuchsia_driver_registrar::DriverRegistrar>);
   status = fdio_service_connect(svc_path.c_str(), remote.release());
   if (status != ZX_OK) {
     fprintf(stderr, "fdio_service_connect failed, pathc %s, status %d\n", svc_path.c_str(), status);
diff --git a/src/devices/bin/driver_host2/driver_host.cc b/src/devices/bin/driver_host2/driver_host.cc
index 137aa9b..c55d659 100644
--- a/src/devices/bin/driver_host2/driver_host.cc
+++ b/src/devices/bin/driver_host2/driver_host.cc
@@ -109,11 +109,11 @@
     fidl::BindServer(loop_->dispatcher(), std::move(request), this);
     return ZX_OK;
   };
-  zx_status_t status =
-      svc_dir->AddEntry(fdf::DriverHost::Name, fbl::MakeRefCounted<fs::Service>(service));
+  zx_status_t status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fdf::DriverHost>,
+                                         fbl::MakeRefCounted<fs::Service>(service));
   if (status != ZX_OK) {
-    LOGF(ERROR, "Failed to add directory entry '%s': %s", fdf::DriverHost::Name,
-         zx_status_get_string(status));
+    LOGF(ERROR, "Failed to add directory entry '%s': %s",
+         fidl::DiscoverableProtocolName<fdf::DriverHost>, zx_status_get_string(status));
   }
   return zx::make_status(status);
 }
diff --git a/src/devices/bin/driver_host2/driver_host_test.cc b/src/devices/bin/driver_host2/driver_host_test.cc
index 6299893..75fa495 100644
--- a/src/devices/bin/driver_host2/driver_host_test.cc
+++ b/src/devices/bin/driver_host2/driver_host_test.cc
@@ -129,7 +129,7 @@
   fidl::WireInterface<fdf::DriverHost>* driver_host() { return &driver_host_; }
 
   void AddEntry(fs::Service::Connector connector) {
-    EXPECT_EQ(ZX_OK, svc_dir_->AddEntry(ftest::Incoming::Name,
+    EXPECT_EQ(ZX_OK, svc_dir_->AddEntry(fidl::DiscoverableProtocolName<ftest::Incoming>,
                                         fbl::MakeRefCounted<fs::Service>(std::move(connector))));
   }
 
@@ -243,7 +243,7 @@
 TEST_F(DriverHostTest, Start_OutgoingServices) {
   auto [driver, outgoing_dir] = StartDriver();
 
-  auto path = fbl::StringPrintf("svc/%s", ftest::Outgoing::Name);
+  auto path = fbl::StringPrintf("svc/%s", fidl::DiscoverableProtocolName<ftest::Outgoing>);
   zx::channel client_end, server_end;
   EXPECT_EQ(ZX_OK, zx::channel::create(0, &client_end, &server_end));
   zx_status_t status =
diff --git a/src/devices/bin/driver_host2/driver_host_test_driver.cc b/src/devices/bin/driver_host2/driver_host_test_driver.cc
index e066e37..22a522d 100644
--- a/src/devices/bin/driver_host2/driver_host_test_driver.cc
+++ b/src/devices/bin/driver_host2/driver_host_test_driver.cc
@@ -36,10 +36,11 @@
     }
 
     // Setup the outgoing service.
-    zx_status_t status = outgoing_.svc_dir()->AddEntry(
-        ftest::Outgoing::Name, fbl::MakeRefCounted<fs::Service>([](zx::channel request) {
-          return fidl_epitaph_write(request.get(), ZX_ERR_STOP);
-        }));
+    zx_status_t status =
+        outgoing_.svc_dir()->AddEntry(fidl::DiscoverableProtocolName<ftest::Outgoing>,
+                                      fbl::MakeRefCounted<fs::Service>([](zx::channel request) {
+                                        return fidl_epitaph_write(request.get(), ZX_ERR_STOP);
+                                      }));
     if (status != ZX_OK) {
       return zx::error(status);
     }
diff --git a/src/devices/bin/driver_manager/coordinator.cc b/src/devices/bin/driver_manager/coordinator.cc
index f01424b..8a1c8b6 100644
--- a/src/devices/bin/driver_manager/coordinator.cc
+++ b/src/devices/bin/driver_manager/coordinator.cc
@@ -138,7 +138,7 @@
     return status;
   }
   std::string registration_svc =
-      "/svc/" + std::string(fuchsia_power_manager::DriverManagerRegistration::Name);
+      fidl::DiscoverableProtocolDefaultPath<fuchsia_power_manager::DriverManagerRegistration>;
 
   status = fdio_service_connect(registration_svc.c_str(), remote.release());
   if (status != ZX_OK) {
@@ -1746,15 +1746,18 @@
         dispatcher_, std::move(request), std::make_unique<SystemStateManager>(this));
     if (status != ZX_OK) {
       LOGF(ERROR, "Failed to bind to client channel for '%s': %s",
-           fuchsia_device_manager::SystemStateTransition::Name, zx_status_get_string(status));
+           fidl::DiscoverableProtocolName<fuchsia_device_manager::SystemStateTransition>,
+           zx_status_get_string(status));
     }
     return status;
   };
-  status = svc_dir->AddEntry(fuchsia_device_manager::SystemStateTransition::Name,
-                             fbl::MakeRefCounted<fs::Service>(system_state_manager_register));
+  status = svc_dir->AddEntry(
+      fidl::DiscoverableProtocolName<fuchsia_device_manager::SystemStateTransition>,
+      fbl::MakeRefCounted<fs::Service>(system_state_manager_register));
   if (status != ZX_OK) {
     LOGF(ERROR, "Failed to add entry in service directory for '%s': %s",
-         fuchsia_device_manager::SystemStateTransition::Name, zx_status_get_string(status));
+         fidl::DiscoverableProtocolName<fuchsia_device_manager::SystemStateTransition>,
+         zx_status_get_string(status));
     return status;
   }
 
@@ -1764,11 +1767,12 @@
             dispatcher_, std::move(request), this);
     if (status != ZX_OK) {
       LOGF(ERROR, "Failed to bind to client channel for '%s': %s",
-           fuchsia_device_manager::BindDebugger::Name, zx_status_get_string(status));
+           fidl::DiscoverableProtocolName<fuchsia_device_manager::BindDebugger>,
+           zx_status_get_string(status));
     }
     return status;
   };
-  status = svc_dir->AddEntry(fuchsia_device_manager::BindDebugger::Name,
+  status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_device_manager::BindDebugger>,
                              fbl::MakeRefCounted<fs::Service>(bind_debugger));
   if (status != ZX_OK) {
     return status;
@@ -1780,12 +1784,14 @@
         dispatcher_, std::move(request), this);
     if (status != ZX_OK) {
       LOGF(ERROR, "Failed to bind to client channel for '%s': %s",
-           fuchsia_device_manager::DriverHostDevelopment::Name, zx_status_get_string(status));
+           fidl::DiscoverableProtocolName<fuchsia_device_manager::DriverHostDevelopment>,
+           zx_status_get_string(status));
     }
     return status;
   };
-  status = svc_dir->AddEntry(fuchsia_device_manager::DriverHostDevelopment::Name,
-                             fbl::MakeRefCounted<fs::Service>(driver_host_dev));
+  status = svc_dir->AddEntry(
+      fidl::DiscoverableProtocolName<fuchsia_device_manager::DriverHostDevelopment>,
+      fbl::MakeRefCounted<fs::Service>(driver_host_dev));
   if (status != ZX_OK) {
     return status;
   }
@@ -1797,8 +1803,9 @@
               dispatcher_, std::move(request), this);
       return ZX_OK;
     };
-    status = svc_dir->AddEntry(fuchsia_driver_registrar::DriverRegistrar::Name,
-                               fbl::MakeRefCounted<fs::Service>(driver_registrar));
+    status =
+        svc_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_driver_registrar::DriverRegistrar>,
+                          fbl::MakeRefCounted<fs::Service>(driver_registrar));
     if (status != ZX_OK) {
       return status;
     }
diff --git a/src/devices/bin/driver_manager/driver_runner.cc b/src/devices/bin/driver_manager/driver_runner.cc
index ed4a87b..ec10e29 100644
--- a/src/devices/bin/driver_manager/driver_runner.cc
+++ b/src/devices/bin/driver_manager/driver_runner.cc
@@ -395,11 +395,11 @@
     fidl::BindServer(dispatcher_, std::move(request), this);
     return ZX_OK;
   };
-  zx_status_t status =
-      svc_dir->AddEntry(frunner::ComponentRunner::Name, fbl::MakeRefCounted<fs::Service>(service));
+  zx_status_t status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<frunner::ComponentRunner>,
+                                         fbl::MakeRefCounted<fs::Service>(service));
   if (status != ZX_OK) {
-    LOGF(ERROR, "Failed to add directory entry '%s': %s", frunner::ComponentRunner::Name,
-         zx_status_get_string(status));
+    LOGF(ERROR, "Failed to add directory entry '%s': %s",
+         fidl::DiscoverableProtocolName<frunner::ComponentRunner>, zx_status_get_string(status));
   }
   return zx::make_status(status);
 }
@@ -557,11 +557,12 @@
   if (endpoints.is_error()) {
     return endpoints.take_error();
   }
-  zx_status_t status = fdio_service_connect_at(create->channel().get(), fdf::DriverHost::Name,
+  zx_status_t status = fdio_service_connect_at(create->channel().get(),
+                                               fidl::DiscoverableProtocolName<fdf::DriverHost>,
                                                endpoints->server.TakeChannel().release());
   if (status != ZX_OK) {
-    LOGF(ERROR, "Failed to connect to service '%s': %s", fdf::DriverHost::Name,
-         zx_status_get_string(status));
+    LOGF(ERROR, "Failed to connect to service '%s': %s",
+         fidl::DiscoverableProtocolName<fdf::DriverHost>, zx_status_get_string(status));
     return zx::error(status);
   }
 
diff --git a/src/devices/bin/driver_manager/main.cc b/src/devices/bin/driver_manager/main.cc
index 0a647e0..a547b96 100644
--- a/src/devices/bin/driver_manager/main.cc
+++ b/src/devices/bin/driver_manager/main.cc
@@ -241,7 +241,7 @@
   if (status != ZX_OK) {
     return status;
   }
-  auto path = fbl::StringPrintf("/svc/%s", fuchsia_boot::Arguments::Name);
+  auto path = fbl::StringPrintf("/svc/%s", fidl::DiscoverableProtocolName<fuchsia_boot::Arguments>);
   status = fdio_service_connect(path.data(), remote.release());
   if (status != ZX_OK) {
     LOGF(ERROR, "Failed to get boot arguments service handle: %s", zx_status_get_string(status));
@@ -296,7 +296,8 @@
     LOGF(INFO, "Starting DriverRunner with root driver URL: %s",
          driver_manager_args.driver_runner_root_driver_url.data());
 
-    const auto realm_path = fbl::StringPrintf("/svc/%s", fuchsia_sys2::Realm::Name);
+    const auto realm_path =
+        fbl::StringPrintf("/svc/%s", fidl::DiscoverableProtocolName<fuchsia_sys2::Realm>);
     auto endpoints = fidl::CreateEndpoints<fuchsia_sys2::Realm>();
     if (endpoints.is_error()) {
       return endpoints.status_value();
diff --git a/src/devices/bin/driver_manager/multiple_device_test.cc b/src/devices/bin/driver_manager/multiple_device_test.cc
index f48695d..0248b77 100644
--- a/src/devices/bin/driver_manager/multiple_device_test.cc
+++ b/src/devices/bin/driver_manager/multiple_device_test.cc
@@ -440,9 +440,10 @@
 
   zx::channel channel, channel_remote;
   ASSERT_OK(zx::channel::create(0, &channel, &channel_remote));
-  std::string svc_dir = "/svc/";
-  std::string service = svc_dir + fuchsia_device_manager::SystemStateTransition::Name;
-  ASSERT_OK(fdio_service_connect_at(services.get(), service.c_str(), channel_remote.release()));
+  ASSERT_OK(fdio_service_connect_at(
+      services.get(),
+      fidl::DiscoverableProtocolDefaultPath<fuchsia_device_manager::SystemStateTransition>,
+      channel_remote.release()));
 
   auto response = fidl::WireCall<fuchsia_device_manager::SystemStateTransition>(
                       zx::unowned_channel(channel.get()))
diff --git a/src/devices/bin/driver_manager/package_resolver.cc b/src/devices/bin/driver_manager/package_resolver.cc
index 900348f..64db639 100644
--- a/src/devices/bin/driver_manager/package_resolver.cc
+++ b/src/devices/bin/driver_manager/package_resolver.cc
@@ -43,7 +43,8 @@
   if (status != ZX_OK) {
     return status;
   }
-  const auto path = fbl::StringPrintf("/svc/%s", fuchsia_pkg::PackageResolver::Name);
+  const auto path =
+      fbl::StringPrintf("/svc/%s", fidl::DiscoverableProtocolName<fuchsia_pkg::PackageResolver>);
   status = fdio_service_connect(path.c_str(), remote.release());
   if (status != ZX_OK) {
     return status;
diff --git a/src/lib/isolated_devmgr/v2_component/support.cc b/src/lib/isolated_devmgr/v2_component/support.cc
index 53a2318..65c77a4 100644
--- a/src/lib/isolated_devmgr/v2_component/support.cc
+++ b/src/lib/isolated_devmgr/v2_component/support.cc
@@ -44,7 +44,7 @@
           [&boot_arguments](zx::channel request, async_dispatcher_t* dispatcher) {
             fidl::BindSingleInFlightOnly(dispatcher, std::move(request), &boot_arguments);
           }),
-      fuchsia_boot::Arguments::Name);
+      fidl::DiscoverableProtocolName<fuchsia_boot::Arguments>);
 
   context->outgoing()->AddPublicService(
       std::make_unique<vfs::Service>([](zx::channel request, async_dispatcher_t* dispatcher) {
@@ -52,7 +52,7 @@
             reinterpret_cast<fidl_dispatch_t*>(fuchsia_kernel_RootJob_dispatch);
         fidl_bind(dispatcher, request.release(), root_job_dispatch, nullptr, &kRootJobOps);
       }),
-      fuchsia_kernel::RootJob::Name);
+      fidl::DiscoverableProtocolName<fuchsia_kernel::RootJob>);
 
   loop.Run();
   return 0;
diff --git a/src/lib/loader_service/loader_service_test_fixture.cc b/src/lib/loader_service/loader_service_test_fixture.cc
index d61b60e..29f132dd 100644
--- a/src/lib/loader_service/loader_service_test_fixture.cc
+++ b/src/lib/loader_service/loader_service_test_fixture.cc
@@ -141,8 +141,6 @@
 
 // static
 zx::status<zx::unowned_resource> LoaderServiceTest::GetVmexResource() {
-  static const std::string kVmexResourcePath = "/svc/" + std::string(fkernel::VmexResource::Name);
-
   static zx::resource vmex_resource;
   if (!vmex_resource.is_valid()) {
     zx::channel client, server;
@@ -150,7 +148,8 @@
     if (status.is_error()) {
       return status.take_error();
     }
-    status = zx::make_status(fdio_service_connect(kVmexResourcePath.c_str(), server.release()));
+    status = zx::make_status(fdio_service_connect(
+        fidl::DiscoverableProtocolDefaultPath<fkernel::VmexResource>, server.release()));
     if (status.is_error()) {
       return status.take_error();
     }
diff --git a/src/lib/storage/fs_management/cpp/admin.cc b/src/lib/storage/fs_management/cpp/admin.cc
index e9a59c7..92878f0 100644
--- a/src/lib/storage/fs_management/cpp/admin.cc
+++ b/src/lib/storage/fs_management/cpp/admin.cc
@@ -197,8 +197,8 @@
     return status;
   }
 
-  std::string path = std::string("/svc/") + fshost::Registry::Name;
-  if ((status = fdio_service_connect(path.c_str(), registry_server.release())) != ZX_OK) {
+  if ((status = fdio_service_connect(fidl::DiscoverableProtocolDefaultPath<fshost::Registry>,
+                                     registry_server.release())) != ZX_OK) {
     return status;
   }
 
diff --git a/src/lib/storage/fs_management/cpp/launch.cc b/src/lib/storage/fs_management/cpp/launch.cc
index 02f35d6..35fa2ea 100644
--- a/src/lib/storage/fs_management/cpp/launch.cc
+++ b/src/lib/storage/fs_management/cpp/launch.cc
@@ -54,8 +54,8 @@
     return ZX_HANDLE_INVALID;
   }
 
-  std::string path = std::string("/svc/") + fboot::WriteOnlyLog::Name;
-  status = fdio_service_connect(path.c_str(), remote.release());
+  status = fdio_service_connect(fidl::DiscoverableProtocolDefaultPath<fboot::WriteOnlyLog>,
+                                remote.release());
   if (status != ZX_OK) {
     fprintf(stderr, "fs-management: Failed to connect to WriteOnlyLog: %d (%s)\n", status,
             zx_status_get_string(status));
diff --git a/src/power/shutdown-shim/main.cc b/src/power/shutdown-shim/main.cc
index 020685f..9a32bdc 100644
--- a/src/power/shutdown-shim/main.cc
+++ b/src/power/shutdown-shim/main.cc
@@ -194,8 +194,8 @@
 // termination state.
 zx_status_t set_system_state_transition_behavior(statecontrol_fidl::wire::SystemPowerState state) {
   zx::channel local;
-  zx_status_t status =
-      connect_to_protocol(&device_manager_fidl::SystemStateTransition::Name[0], &local);
+  zx_status_t status = connect_to_protocol(
+      fidl::DiscoverableProtocolName<device_manager_fidl::SystemStateTransition>, &local);
   if (status != ZX_OK) {
     fprintf(stderr, "[shutdown-shim]: error connecting to driver_manager\n");
     return status;
@@ -220,7 +220,8 @@
 // complete.
 zx_status_t initiate_component_shutdown() {
   zx::channel local;
-  zx_status_t status = connect_to_protocol(&sys2_fidl::SystemController::Name[0], &local);
+  zx_status_t status =
+      connect_to_protocol(fidl::DiscoverableProtocolName<sys2_fidl::SystemController>, &local);
   if (status != ZX_OK) {
     fprintf(stderr, "[shutdown-shim]: error connecting to component_manager\n");
     return status;
@@ -360,7 +361,8 @@
                             statecontrol_fidl::wire::RebootReason* reboot_reason) {
   printf("[shutdown-shim]: checking power_manager liveness\n");
   zx::channel local;
-  zx_status_t status = connect_to_protocol_with_timeout(&statecontrol_fidl::Admin::Name[0], &local);
+  zx_status_t status = connect_to_protocol_with_timeout(
+      fidl::DiscoverableProtocolName<statecontrol_fidl::Admin>, &local);
   if (status == ZX_OK) {
     printf("[shutdown-shim]: trying to forward command\n");
     status = send_command(fidl::WireSyncClient<statecontrol_fidl::Admin>(std::move(local)),
@@ -436,7 +438,8 @@
 void StateControlAdminServer::Mexec(
     fidl::WireInterface<statecontrol_fidl::Admin>::MexecCompleter::Sync& completer) {
   zx::channel local;
-  zx_status_t status = connect_to_protocol_with_timeout(&statecontrol_fidl::Admin::Name[0], &local);
+  zx_status_t status = connect_to_protocol_with_timeout(
+      fidl::DiscoverableProtocolName<statecontrol_fidl::Admin>, &local);
   if (status == ZX_OK) {
     status = send_command(fidl::WireSyncClient<statecontrol_fidl::Admin>(std::move(local)),
                           statecontrol_fidl::wire::SystemPowerState::MEXEC, nullptr);
@@ -521,7 +524,7 @@
   auto outgoing_dir = fbl::MakeRefCounted<fs::PseudoDir>();
   auto svc_dir = fbl::MakeRefCounted<fs::PseudoDir>();
 
-  svc_dir->AddEntry(statecontrol_fidl::Admin::Name,
+  svc_dir->AddEntry(fidl::DiscoverableProtocolName<statecontrol_fidl::Admin>,
                     StateControlAdminServer::Create(loop.dispatcher()));
   outgoing_dir->AddEntry("svc", std::move(svc_dir));
 
diff --git a/src/storage/blobfs/runner.cc b/src/storage/blobfs/runner.cc
index fae2cdcd..5721aac 100644
--- a/src/storage/blobfs/runner.cc
+++ b/src/storage/blobfs/runner.cc
@@ -94,10 +94,11 @@
       outgoing->AddEntry("svc", svc_dir);
 
       query_svc_ = fbl::MakeRefCounted<QueryService>(loop_->dispatcher(), blobfs_.get(), this);
-      svc_dir->AddEntry(fuchsia_fs::Query::Name, query_svc_);
+      svc_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_fs::Query>, query_svc_);
 
       health_check_svc_ = fbl::MakeRefCounted<HealthCheckService>(loop_->dispatcher(), *blobfs_);
-      svc_dir->AddEntry(fuchsia_update_verify::BlobfsVerifier::Name, health_check_svc_);
+      svc_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_update_verify::BlobfsVerifier>,
+                        health_check_svc_);
 
       export_root = std::move(outgoing);
       break;
diff --git a/src/storage/blobfs/test/integration/query_service_test.cc b/src/storage/blobfs/test/integration/query_service_test.cc
index 2502acf..c14d818 100644
--- a/src/storage/blobfs/test/integration/query_service_test.cc
+++ b/src/storage/blobfs/test/integration/query_service_test.cc
@@ -36,7 +36,8 @@
     EXPECT_EQ(endpoints.status_value(), ZX_OK);
     auto [query_client_end, query_server_end] = *std::move(endpoints);
 
-    std::string query_service_path = std::string("svc/") + fuchsia_fs::Query::Name;
+    std::string query_service_path =
+        std::string("svc/") + fidl::DiscoverableProtocolName<fuchsia_fs::Query>;
     EXPECT_EQ(
         fdio_service_connect_at(fs().GetOutgoingDirectory()->get(), query_service_path.c_str(),
                                 query_server_end.TakeChannel().release()),
diff --git a/src/storage/blobfs/test/integration/verifier_service_test.cc b/src/storage/blobfs/test/integration/verifier_service_test.cc
index d4251c6..0420aa4 100644
--- a/src/storage/blobfs/test/integration/verifier_service_test.cc
+++ b/src/storage/blobfs/test/integration/verifier_service_test.cc
@@ -12,6 +12,7 @@
 
 #include <gtest/gtest.h>
 
+#include "lib/fidl/llcpp/connect_service.h"
 #include "src/storage/blobfs/test/integration/blobfs_fixtures.h"
 
 namespace blobfs {
@@ -26,8 +27,8 @@
     EXPECT_EQ(endpoints.status_value(), ZX_OK);
     auto [client_end, server_end] = *std::move(endpoints);
 
-    std::string service_path = std::string("svc/") + fuv::BlobfsVerifier::Name;
-    EXPECT_EQ(fdio_service_connect_at(fs().GetOutgoingDirectory()->get(), service_path.c_str(),
+    EXPECT_EQ(fdio_service_connect_at(fs().GetOutgoingDirectory()->get(),
+                                      fidl::DiscoverableProtocolDefaultPath<fuv::BlobfsVerifier>,
                                       server_end.TakeChannel().release()),
               ZX_OK);
     return fidl::WireSyncClient<fuv::BlobfsVerifier>(std::move(client_end));
diff --git a/src/storage/factory/factoryfs/runner.cc b/src/storage/factory/factoryfs/runner.cc
index 55befc8..d211beaa 100644
--- a/src/storage/factory/factoryfs/runner.cc
+++ b/src/storage/factory/factoryfs/runner.cc
@@ -62,7 +62,7 @@
       auto svc_dir = fbl::MakeRefCounted<fs::PseudoDir>();
       outgoing->AddEntry("svc", svc_dir);
       query_svc_ = fbl::MakeRefCounted<QueryService>(loop_->dispatcher(), factoryfs_.get(), this);
-      svc_dir->AddEntry(fuchsia_fs::Query::Name, query_svc_);
+      svc_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_fs::Query>, query_svc_);
       export_root = std::move(outgoing);
       break;
   }
diff --git a/src/storage/fshost/filesystem-mounter.cc b/src/storage/fshost/filesystem-mounter.cc
index 4b98cc9..0cb94c4 100644
--- a/src/storage/fshost/filesystem-mounter.cc
+++ b/src/storage/fshost/filesystem-mounter.cc
@@ -189,8 +189,9 @@
     FX_LOGS(ERROR) << "failed to add diagnostic directory for blobfs: "
                    << zx_status_get_string(status);
   }
-  status = fshost_.ForwardFsService(FsManager::MountPoint::kBlob,
-                                    fuchsia_update_verify::BlobfsVerifier::Name);
+  status = fshost_.ForwardFsService(
+      FsManager::MountPoint::kBlob,
+      fidl::DiscoverableProtocolName<fuchsia_update_verify::BlobfsVerifier>);
   if (status != ZX_OK) {
     FX_LOGS(ERROR) << "failed to forward BlobfsVerifier service for blobfs: "
                    << zx_status_get_string(status);
diff --git a/src/storage/fshost/fs-manager.cc b/src/storage/fshost/fs-manager.cc
index 61bee3d..4b47b42 100644
--- a/src/storage/fshost/fs-manager.cc
+++ b/src/storage/fshost/fs-manager.cc
@@ -108,10 +108,10 @@
           return ZX_OK;
         }));
   }
-  svc_dir_->AddEntry(fuchsia_fshost::Admin::Name,
+  svc_dir_->AddEntry(fidl::DiscoverableProtocolName<fuchsia_fshost::Admin>,
                      AdminServer::Create(this, global_loop_->dispatcher()));
 
-  svc_dir_->AddEntry(fuchsia_fshost::BlockWatcher::Name,
+  svc_dir_->AddEntry(fidl::DiscoverableProtocolName<fuchsia_fshost::BlockWatcher>,
                      BlockWatcherServer::Create(global_loop_->dispatcher(), watcher));
 
   outgoing_dir->AddEntry("svc", svc_dir_);
diff --git a/src/storage/fshost/fshost-boot-args.cc b/src/storage/fshost/fshost-boot-args.cc
index ecf947f..462192c 100644
--- a/src/storage/fshost/fshost-boot-args.cc
+++ b/src/storage/fshost/fshost-boot-args.cc
@@ -10,6 +10,8 @@
 
 #include <fbl/string_printf.h>
 
+#include "lib/fidl/llcpp/connect_service.h"
+
 namespace devmgr {
 
 // static
@@ -24,8 +26,8 @@
                       "environment and continuing";
     return std::make_shared<FshostBootArgs>(std::nullopt);
   }
-  auto path = fbl::StringPrintf("/svc/%s", fuchsia_boot::Arguments::Name);
-  status = fdio_service_connect(path.data(), remote.release());
+  status = fdio_service_connect(fidl::DiscoverableProtocolDefaultPath<fuchsia_boot::Arguments>,
+                                remote.release());
   if (status != ZX_OK) {
     // This service might be missing if we're running in a test environment. Log
     // the error and continue.
diff --git a/src/storage/fshost/fshost-exposed-dir-test.cc b/src/storage/fshost/fshost-exposed-dir-test.cc
index 67419d1..1c04dd2 100644
--- a/src/storage/fshost/fshost-exposed-dir-test.cc
+++ b/src/storage/fshost/fshost-exposed-dir-test.cc
@@ -84,7 +84,7 @@
       openat(export_dir_fd.get(), svc_name.c_str(), fuchsia::io::OPEN_FLAG_DESCRIBE, 0644));
   EXPECT_TRUE(blobfs_diag_dir_fd) << "failed to open " << svc_name << ": " << strerror(errno);
 
-  svc_name = fuchsia_update_verify::BlobfsVerifier::Name;
+  svc_name = fidl::DiscoverableProtocolName<fuchsia_update_verify::BlobfsVerifier>;
   fbl::unique_fd blobfs_health_check_dir_fd(
       openat(export_dir_fd.get(), svc_name.c_str(), fuchsia::io::OPEN_FLAG_DESCRIBE, 0644));
   EXPECT_TRUE(blobfs_health_check_dir_fd)
diff --git a/src/storage/fshost/fshost_integration_test.cc b/src/storage/fshost/fshost_integration_test.cc
index ed8db40..90dd7fa 100644
--- a/src/storage/fshost/fshost_integration_test.cc
+++ b/src/storage/fshost/fshost_integration_test.cc
@@ -39,7 +39,7 @@
   ASSERT_EQ(status.status_value(), ZX_OK);
   status = zx::make_status(
       exposed_dir_->Open(fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE, 0,
-                         fuchsia_fshost::BlockWatcher::Name,
+                         fidl::DiscoverableProtocolName<fuchsia_fshost::BlockWatcher>,
                          fidl::InterfaceRequest<fuchsia::io::Node>(std::move(request))));
   ASSERT_EQ(status.status_value(), ZX_OK);
 }
diff --git a/src/storage/fshost/registry.cc b/src/storage/fshost/registry.cc
index 27aefdf..5fc7a74 100644
--- a/src/storage/fshost/registry.cc
+++ b/src/storage/fshost/registry.cc
@@ -19,12 +19,13 @@
   // Create a "tracking directory", capable of monitoring registered filesystems,
   // and detaching them once they are unmounted.
   auto filesystems = fbl::MakeRefCounted<fs::PseudoDir>();
-  zx_status_t status = root_->AddEntry(fuchsia_fshost::Filesystems::Name, filesystems);
+  zx_status_t status =
+      root_->AddEntry(fidl::DiscoverableProtocolName<fuchsia_fshost::Filesystems>, filesystems);
   ZX_ASSERT(status == ZX_OK);
 
   // Create a service node, which clients may use to communicate with the registry.
   svc_ = fbl::MakeRefCounted<fshost::RegistryVnode>(vfs_.dispatcher(), std::move(filesystems));
-  status = root_->AddEntry(fuchsia_fshost::Registry::Name, svc_);
+  status = root_->AddEntry(fidl::DiscoverableProtocolName<fuchsia_fshost::Registry>, svc_);
   ZX_ASSERT(status == ZX_OK);
 }
 
diff --git a/src/storage/lib/paver/provider.cc b/src/storage/lib/paver/provider.cc
index 5ec6c43..859bb50 100644
--- a/src/storage/lib/paver/provider.cc
+++ b/src/storage/lib/paver/provider.cc
@@ -24,7 +24,7 @@
 
 zx_status_t Connect(void* ctx, async_dispatcher_t* dispatcher, const char* service_name,
                     zx_handle_t request) {
-  if (!strcmp(service_name, fuchsia_paver::Paver::Name)) {
+  if (!strcmp(service_name, fidl::DiscoverableProtocolName<fuchsia_paver::Paver>)) {
     auto* paver = reinterpret_cast<paver::Paver*>(ctx);
     paver->set_dispatcher(dispatcher);
     return fidl::BindSingleInFlightOnly(dispatcher, zx::channel(request), paver);
@@ -59,7 +59,7 @@
 void Release(void* ctx) { delete static_cast<paver::Paver*>(ctx); }
 
 constexpr const char* kPaverServices[] = {
-    fuchsia_paver::Paver::Name,
+    fidl::DiscoverableProtocolName<fuchsia_paver::Paver>,
     nullptr,
 };
 
diff --git a/src/storage/lib/paver/test/paversvc-test.cc b/src/storage/lib/paver/test/paversvc-test.cc
index de02d85..407449d 100644
--- a/src/storage/lib/paver/test/paversvc-test.cc
+++ b/src/storage/lib/paver/test/paversvc-test.cc
@@ -218,7 +218,7 @@
  public:
   explicit FakeSvc(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher), vfs_(dispatcher) {
     root_dir_ = fbl::MakeRefCounted<fs::PseudoDir>();
-    root_dir_->AddEntry(fuchsia_boot::Arguments::Name,
+    root_dir_->AddEntry(fidl::DiscoverableProtocolName<fuchsia_boot::Arguments>,
                         fbl::MakeRefCounted<fs::Service>([this](zx::channel request) {
                           return fake_boot_args_.Connect(dispatcher_, std::move(request));
                         }));
@@ -294,7 +294,8 @@
   ASSERT_OK(paver_get_service_provider()->ops->init(&provider_ctx_));
 
   ASSERT_OK(paver_get_service_provider()->ops->connect(
-      provider_ctx_, loop_.dispatcher(), fuchsia_paver::Paver::Name, server.release()));
+      provider_ctx_, loop_.dispatcher(), fidl::DiscoverableProtocolName<fuchsia_paver::Paver>,
+      server.release()));
   loop_.StartThread("paver-svc-test-loop");
   loop2_.StartThread("paver-svc-test-loop-2");
 }
@@ -1785,7 +1786,8 @@
     ASSERT_OK(IsolatedDevmgr::Create(std::move(args), &devmgr_));
 
     // Forward the block watcher FIDL interface from the devmgr.
-    fake_svc_.ForwardServiceTo(fuchsia_fshost::BlockWatcher::Name, devmgr_.fshost_outgoing_dir());
+    fake_svc_.ForwardServiceTo(fidl::DiscoverableProtocolName<fuchsia_fshost::BlockWatcher>,
+                               devmgr_.fshost_outgoing_dir());
 
     fbl::unique_fd fd;
     ASSERT_OK(RecursiveWaitForFile(devmgr_.devfs_root(), "misc/ramctl", &fd));
@@ -1896,7 +1898,8 @@
     ASSERT_OK(driver_integration_test::IsolatedDevmgr::Create(&args, &devmgr_));
 
     // Forward the block watcher FIDL interface from the devmgr.
-    fake_svc_.ForwardServiceTo(fuchsia_fshost::BlockWatcher::Name, devmgr_.fshost_outgoing_dir());
+    fake_svc_.ForwardServiceTo(fidl::DiscoverableProtocolName<fuchsia_fshost::BlockWatcher>,
+                               devmgr_.fshost_outgoing_dir());
 
     fbl::unique_fd fd;
     ASSERT_OK(RecursiveWaitForFile(devmgr_.devfs_root(), "misc/ramctl", &fd));
diff --git a/tools/fidl/fidlc/testdata/protocols.test.fidl b/tools/fidl/fidlc/testdata/protocols.test.fidl
index 63c0ba2..40f1d4f 100644
--- a/tools/fidl/fidlc/testdata/protocols.test.fidl
+++ b/tools/fidl/fidlc/testdata/protocols.test.fidl
@@ -60,4 +60,3 @@
 protocol DiscoverableProtocol {
     Method();
 };
-
diff --git a/tools/fidl/fidlgen_llcpp/BUILD.gn b/tools/fidl/fidlgen_llcpp/BUILD.gn
index 74f5d65..bd62c2f 100644
--- a/tools/fidl/fidlgen_llcpp/BUILD.gn
+++ b/tools/fidl/fidlgen_llcpp/BUILD.gn
@@ -32,6 +32,7 @@
     "codegen/fragment_method_result.tmpl.go",
     "codegen/fragment_method_unownedresult.tmpl.go",
     "codegen/fragment_protocol.tmpl.go",
+    "codegen/fragment_protocol_details.tmpl.go",
     "codegen/fragment_protocol_dispatcher.tmpl.go",
     "codegen/fragment_protocol_event_handler.tmpl.go",
     "codegen/fragment_protocol_interface.tmpl.go",
diff --git a/tools/fidl/fidlgen_llcpp/codegen/codegen.go b/tools/fidl/fidlgen_llcpp/codegen/codegen.go
index 199d8d7..92c12b3 100644
--- a/tools/fidl/fidlgen_llcpp/codegen/codegen.go
+++ b/tools/fidl/fidlgen_llcpp/codegen/codegen.go
@@ -201,6 +201,7 @@
 		fragmentMethodResultTmpl,
 		fragmentMethodUnownedResultTmpl,
 		fragmentProtocolTmpl,
+		fragmentProtocolDetailsTmpl,
 		fragmentProtocolDispatcherTmpl,
 		fragmentProtocolEventHandlerTmpl,
 		fragmentProtocolInterfaceTmpl,
diff --git a/tools/fidl/fidlgen_llcpp/codegen/fragment_protocol.tmpl.go b/tools/fidl/fidlgen_llcpp/codegen/fragment_protocol.tmpl.go
index 883b6da..b0066d3 100644
--- a/tools/fidl/fidlgen_llcpp/codegen/fragment_protocol.tmpl.go
+++ b/tools/fidl/fidlgen_llcpp/codegen/fragment_protocol.tmpl.go
@@ -52,11 +52,6 @@
 class {{ .Name }} final {
   {{ .Name }}() = delete;
  public:
-  {{- if .DiscoverableName }}
-    static constexpr char Name[] = {{ .DiscoverableName }};
-  {{- end }}
-
-  {{ "" }}
   {{- range .Methods }}
     {{- .Docs }}
     class {{ .Marker.Self }} final {
@@ -65,6 +60,7 @@
   {{- end }}
 };
 
+{{- template "ProtocolDetailsDeclaration" . }}
 {{- template "ProtocolDispatcherDeclaration" . }}
 
 {{- range .Methods }}
diff --git a/tools/fidl/fidlgen_llcpp/codegen/fragment_protocol_details.tmpl.go b/tools/fidl/fidlgen_llcpp/codegen/fragment_protocol_details.tmpl.go
new file mode 100644
index 0000000..fafeac8
--- /dev/null
+++ b/tools/fidl/fidlgen_llcpp/codegen/fragment_protocol_details.tmpl.go
@@ -0,0 +1,21 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package codegen
+
+// fragmentProtocolDetailsTmpl contains the definition for
+// fidl::internal::ProtocolDetails<Protocol>.
+const fragmentProtocolDetailsTmpl = `
+{{- define "ProtocolDetailsDeclaration" }}
+{{ EnsureNamespace "" }}
+{{- IfdefFuchsia }}
+template<>
+struct {{ .ProtocolDetails }} {
+  {{- if .DiscoverableName }}
+    static constexpr char DiscoverableName[] = {{ .DiscoverableName }};
+  {{- end }}
+};
+{{- EndifFuchsia }}
+{{- end }}
+`
diff --git a/tools/fidl/fidlgen_llcpp/goldens/bindings_denylist.h.golden b/tools/fidl/fidlgen_llcpp/goldens/bindings_denylist.h.golden
index 9f54d0d..acc71e1 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/bindings_denylist.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/bindings_denylist.h.golden
@@ -148,8 +148,16 @@
     LibfuzzerNeedsNonemptyProtocol() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_bindingsdenylist
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps>
@@ -164,9 +172,8 @@
           impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_bindingsdenylist {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_bindingsdenylist
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_bindingsdenylist::OnlyLibfuzzerAndDeps::
                                LibfuzzerNeedsNonemptyProtocol>
@@ -745,8 +752,16 @@
 
  public:
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_bindingsdenylist
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_bindingsdenylist::OnlyCppAndDeps> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_bindingsdenylist::OnlyCppAndDeps>
@@ -759,9 +774,7 @@
       ::fidl::WireInterface<::fidl_test_bindingsdenylist::OnlyCppAndDeps>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_bindingsdenylist {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_bindingsdenylist
 
 // Methods to make a sync FIDL call directly on an unowned channel or a
 // const reference to a
diff --git a/tools/fidl/fidlgen_llcpp/goldens/doc_comments.h.golden b/tools/fidl/fidlgen_llcpp/goldens/doc_comments.h.golden
index 2dbe002..bc57777 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/doc_comments.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/doc_comments.h.golden
@@ -832,8 +832,15 @@
     OnEvent() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_doccomments
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_doccomments::Interface> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_doccomments::Interface>
     final {
@@ -845,9 +852,8 @@
       ::fidl::WireInterface<::fidl_test_doccomments::Interface>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_doccomments {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_doccomments
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_doccomments::Interface::Method> final {
   FIDL_ALIGNDECL
diff --git a/tools/fidl/fidlgen_llcpp/goldens/empty_struct.h.golden b/tools/fidl/fidlgen_llcpp/goldens/empty_struct.h.golden
index 8c6a996..81c4787 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/empty_struct.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/empty_struct.h.golden
@@ -166,8 +166,16 @@
     SendAndReceive() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_emptystruct
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_emptystruct::EmptyProtocol> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_emptystruct::EmptyProtocol>
     final {
@@ -179,9 +187,8 @@
       ::fidl::WireInterface<::fidl_test_emptystruct::EmptyProtocol>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_emptystruct {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_emptystruct
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_emptystruct::EmptyProtocol::Send> final {
   FIDL_ALIGNDECL
diff --git a/tools/fidl/fidlgen_llcpp/goldens/error.h.golden b/tools/fidl/fidlgen_llcpp/goldens/error.h.golden
index 9c8c913..9e05f50 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/error.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/error.h.golden
@@ -293,8 +293,15 @@
     foo() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_error
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_error::Example> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_error::Example> final {
   WireDispatcher() = delete;
@@ -305,9 +312,8 @@
       ::fidl::WireInterface<::fidl_test_error::Example>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_error {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_error
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_error::Example::foo> final {
   FIDL_ALIGNDECL
diff --git a/tools/fidl/fidlgen_llcpp/goldens/foreign_type_in_response_used_through_compose.h.golden b/tools/fidl/fidlgen_llcpp/goldens/foreign_type_in_response_used_through_compose.h.golden
index d788564..a3e3cca 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/foreign_type_in_response_used_through_compose.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/foreign_type_in_response_used_through_compose.h.golden
@@ -55,8 +55,16 @@
     GetFoo() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_foreigntypeinresponseusedthroughcompose
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_foreigntypeinresponseusedthroughcompose::Top> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_foreigntypeinresponseusedthroughcompose::Top>
@@ -71,9 +79,8 @@
           ::fidl_test_foreigntypeinresponseusedthroughcompose::Top>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_foreigntypeinresponseusedthroughcompose {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_foreigntypeinresponseusedthroughcompose
+
 template <>
 struct ::fidl::WireRequest<
     ::fidl_test_foreigntypeinresponseusedthroughcompose::Top::GetFoo>
diff --git a/tools/fidl/fidlgen_llcpp/goldens/handles.h.golden b/tools/fidl/fidlgen_llcpp/goldens/handles.h.golden
index 1783f37..160ba48 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/handles.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/handles.h.golden
@@ -304,8 +304,15 @@
 
  public:
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_handles
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_handles::SomeProtocol> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_handles::SomeProtocol>
     final {
@@ -317,9 +324,7 @@
       ::fidl::WireInterface<::fidl_test_handles::SomeProtocol>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_handles {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_handles
 
 // Methods to make a sync FIDL call directly on an unowned channel or a
 // const reference to a |fidl::ClientEnd<::fidl_test_handles::SomeProtocol>|,
diff --git a/tools/fidl/fidlgen_llcpp/goldens/inheritance.h.golden b/tools/fidl/fidlgen_llcpp/goldens/inheritance.h.golden
index 73942a9..d81d040 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/inheritance.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/inheritance.h.golden
@@ -53,8 +53,15 @@
     foo() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_inheritance
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_inheritance::super> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_inheritance::super> final {
   WireDispatcher() = delete;
@@ -65,9 +72,8 @@
       ::fidl::WireInterface<::fidl_test_inheritance::super>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_inheritance {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_inheritance
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_inheritance::super::foo> final {
   FIDL_ALIGNDECL
@@ -620,8 +626,15 @@
     foo() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_inheritance
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_inheritance::sub> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_inheritance::sub> final {
   WireDispatcher() = delete;
@@ -632,9 +645,8 @@
       ::fidl::WireInterface<::fidl_test_inheritance::sub>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_inheritance {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_inheritance
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_inheritance::sub::foo> final {
   FIDL_ALIGNDECL
diff --git a/tools/fidl/fidlgen_llcpp/goldens/inheritance_with_recursive_decl.h.golden b/tools/fidl/fidlgen_llcpp/goldens/inheritance_with_recursive_decl.h.golden
index 39c01a3..e3db167 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/inheritance_with_recursive_decl.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/inheritance_with_recursive_decl.h.golden
@@ -55,8 +55,16 @@
     First() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_inheritancewithrecursivedecl
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_inheritancewithrecursivedecl::Parent> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_inheritancewithrecursivedecl::Parent>
@@ -71,9 +79,8 @@
           impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_inheritancewithrecursivedecl {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_inheritancewithrecursivedecl
+
 template <>
 struct ::fidl::WireRequest<
     ::fidl_test_inheritancewithrecursivedecl::Parent::First>
@@ -474,8 +481,16 @@
     Second() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_inheritancewithrecursivedecl
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_inheritancewithrecursivedecl::Child> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_inheritancewithrecursivedecl::Child>
@@ -490,9 +505,8 @@
           impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_inheritancewithrecursivedecl {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_inheritancewithrecursivedecl
+
 template <>
 struct ::fidl::WireRequest<
     ::fidl_test_inheritancewithrecursivedecl::Child::First>
diff --git a/tools/fidl/fidlgen_llcpp/goldens/nullable.h.golden b/tools/fidl/fidlgen_llcpp/goldens/nullable.h.golden
index 0e0a7cb..07f40f6 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/nullable.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/nullable.h.golden
@@ -875,8 +875,16 @@
     Add() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_nullable
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_nullable::SimpleProtocol> {
+};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_nullable::SimpleProtocol>
     final {
@@ -888,9 +896,8 @@
       ::fidl::WireInterface<::fidl_test_nullable::SimpleProtocol>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_nullable {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_nullable
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_nullable::SimpleProtocol::Add> final {
   FIDL_ALIGNDECL
diff --git a/tools/fidl/fidlgen_llcpp/goldens/placement_of_attributes.h.golden b/tools/fidl/fidlgen_llcpp/goldens/placement_of_attributes.h.golden
index c3d9019..751f780 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/placement_of_attributes.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/placement_of_attributes.h.golden
@@ -625,8 +625,16 @@
     Method() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_placementofattributes
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_placementofattributes::ExampleProtocol> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_placementofattributes::ExampleProtocol>
@@ -641,9 +649,8 @@
           impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_placementofattributes {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_placementofattributes
+
 template <>
 struct ::fidl::WireRequest<
     ::fidl_test_placementofattributes::ExampleProtocol::Method>
diff --git a/tools/fidl/fidlgen_llcpp/goldens/protocol_request.h.golden b/tools/fidl/fidlgen_llcpp/goldens/protocol_request.h.golden
index ac43c0d..6cd1d5d 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/protocol_request.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/protocol_request.h.golden
@@ -82,8 +82,16 @@
     TakeChildRequest() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_protocolrequest
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_protocolrequest::Parent> {
+};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_protocolrequest::Parent>
     final {
@@ -95,9 +103,8 @@
       ::fidl::WireInterface<::fidl_test_protocolrequest::Parent>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_protocolrequest {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_protocolrequest
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_protocolrequest::Parent::GetChild>
     final {
@@ -1647,8 +1654,15 @@
 
  public:
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_protocolrequest
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_protocolrequest::Child> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_protocolrequest::Child>
     final {
@@ -1660,9 +1674,7 @@
       ::fidl::WireInterface<::fidl_test_protocolrequest::Child>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_protocolrequest {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_protocolrequest
 
 // Methods to make a sync FIDL call directly on an unowned channel or a
 // const reference to a |fidl::ClientEnd<::fidl_test_protocolrequest::Child>|,
diff --git a/tools/fidl/fidlgen_llcpp/goldens/protocols.h.golden b/tools/fidl/fidlgen_llcpp/goldens/protocols.h.golden
index d9d4277..9a3b868 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/protocols.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/protocols.h.golden
@@ -904,14 +904,23 @@
   DiscoverableProtocol() = delete;
 
  public:
-  static constexpr char Name[] = "fidl.test.protocols.DiscoverableProtocol";
-
   class Method final {
     Method() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_protocols
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_protocols::DiscoverableProtocol> {
+  static constexpr char DiscoverableName[] =
+      "fidl.test.protocols.DiscoverableProtocol";
+};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_protocols::DiscoverableProtocol>
@@ -924,9 +933,8 @@
       ::fidl::WireInterface<::fidl_test_protocols::DiscoverableProtocol>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_protocols {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_protocols
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_protocols::DiscoverableProtocol::Method>
     final {
@@ -1243,8 +1251,16 @@
     Event() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_protocols
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_protocols::Transitional> {
+};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_protocols::Transitional>
     final {
@@ -1256,9 +1272,8 @@
       ::fidl::WireInterface<::fidl_test_protocols::Transitional>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_protocols {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_protocols
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_protocols::Transitional::Request> final {
   FIDL_ALIGNDECL
@@ -2222,8 +2237,16 @@
     MutateSocket() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_protocols
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_protocols::ChannelProtocol> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_protocols::ChannelProtocol>
     final {
@@ -2235,9 +2258,8 @@
       ::fidl::WireInterface<::fidl_test_protocols::ChannelProtocol>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_protocols {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_protocols
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_protocols::ChannelProtocol::MethodA>
     final {
@@ -4219,8 +4241,16 @@
     OnWithResponse() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_protocols
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_protocols::WithAndWithoutRequestResponse> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_protocols::WithAndWithoutRequestResponse>
@@ -4235,9 +4265,8 @@
           ::fidl_test_protocols::WithAndWithoutRequestResponse>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_protocols {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_protocols
+
 template <>
 struct ::fidl::WireRequest<
     ::fidl_test_protocols::WithAndWithoutRequestResponse::NoRequestNoResponse>
@@ -7112,8 +7141,16 @@
     ErrorAsEnum() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_protocols
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_protocols::WithErrorSyntax> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_protocols::WithErrorSyntax>
     final {
@@ -7125,9 +7162,8 @@
       ::fidl::WireInterface<::fidl_test_protocols::WithErrorSyntax>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_protocols {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_protocols
+
 template <>
 struct ::fidl::WireRequest<
     ::fidl_test_protocols::WithErrorSyntax::ResponseAsStruct>
diff --git a/tools/fidl/fidlgen_llcpp/goldens/request_flexible_envelope.h.golden b/tools/fidl/fidlgen_llcpp/goldens/request_flexible_envelope.h.golden
index 6150f86..2eda666 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/request_flexible_envelope.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/request_flexible_envelope.h.golden
@@ -350,8 +350,16 @@
     RequestFlexibleResponseStrict() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_requestflexibleenvelope
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_requestflexibleenvelope::Protocol> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_requestflexibleenvelope::Protocol>
@@ -366,9 +374,8 @@
           impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_requestflexibleenvelope {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_requestflexibleenvelope
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_requestflexibleenvelope::Protocol::
                                RequestStrictResponseFlexible>
diff --git a/tools/fidl/fidlgen_llcpp/goldens/service.h.golden b/tools/fidl/fidlgen_llcpp/goldens/service.h.golden
index 6cc0f6f..3910d47 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/service.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/service.h.golden
@@ -63,8 +63,16 @@
     MethodOnSecond() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_service
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_service::SecondProtocol> {
+};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_service::SecondProtocol>
     final {
@@ -76,9 +84,8 @@
       ::fidl::WireInterface<::fidl_test_service::SecondProtocol>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_service {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_service
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_service::SecondProtocol::MethodOnSecond>
     final {
@@ -372,8 +379,15 @@
     MethodOnFirst() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_service
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_service::FirstProtocol> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_service::FirstProtocol>
     final {
@@ -385,9 +399,8 @@
       ::fidl::WireInterface<::fidl_test_service::FirstProtocol>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_service {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_service
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_service::FirstProtocol::MethodOnFirst>
     final {
diff --git a/tools/fidl/fidlgen_llcpp/goldens/transitive_dependencies_compose.h.golden b/tools/fidl/fidlgen_llcpp/goldens/transitive_dependencies_compose.h.golden
index 526d49e..3287b3d 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/transitive_dependencies_compose.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/transitive_dependencies_compose.h.golden
@@ -55,8 +55,16 @@
     GetFoo() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_transitivedependenciescompose
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<
+    ::fidl_test_transitivedependenciescompose::Top> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<
     ::fidl_test_transitivedependenciescompose::Top>
@@ -71,9 +79,8 @@
           impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_transitivedependenciescompose {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_transitivedependenciescompose
+
 template <>
 struct ::fidl::WireRequest<
     ::fidl_test_transitivedependenciescompose::Top::GetFoo>
diff --git a/tools/fidl/fidlgen_llcpp/goldens/union.h.golden b/tools/fidl/fidlgen_llcpp/goldens/union.h.golden
index ef0db74..3c39df2 100644
--- a/tools/fidl/fidlgen_llcpp/goldens/union.h.golden
+++ b/tools/fidl/fidlgen_llcpp/goldens/union.h.golden
@@ -3174,8 +3174,15 @@
     FlexibleXUnionHenceResponseMustBeHeapAllocated() = delete;
   };
 };
-#ifdef __Fuchsia__
 }  // namespace fidl_test_union
+#ifdef __Fuchsia__
+
+template <>
+struct ::fidl::internal::ProtocolDetails<::fidl_test_union::TestProtocol> {};
+#endif  // __Fuchsia__
+
+#ifdef __Fuchsia__
+
 template <>
 struct ::fidl::internal::WireDispatcher<::fidl_test_union::TestProtocol> final {
   WireDispatcher() = delete;
@@ -3186,9 +3193,8 @@
       ::fidl::WireInterface<::fidl_test_union::TestProtocol>* impl,
       fidl_incoming_msg_t* msg, ::fidl::Transaction* txn);
 };
-namespace fidl_test_union {
 #endif  // __Fuchsia__
-}  // namespace fidl_test_union
+
 template <>
 struct ::fidl::WireRequest<::fidl_test_union::TestProtocol::
                                StrictXUnionHenceResponseMayBeStackAllocated>
diff --git a/tools/fidl/lib/fidlgen_cpp/protocol.go b/tools/fidl/lib/fidlgen_cpp/protocol.go
index f08e08a..596ce88 100644
--- a/tools/fidl/lib/fidlgen_cpp/protocol.go
+++ b/tools/fidl/lib/fidlgen_cpp/protocol.go
@@ -99,7 +99,7 @@
 }
 
 // These correspond to templated classes forward-declared in
-// /zircon/system/ulib/fidl/include/lib/fidl/llcpp/wire_messaging.h
+// //zircon/system/ulib/fidl/include/lib/fidl/llcpp/wire_messaging.h
 var (
 	// Protocol related
 	WireSyncClient            = fidlNs.Member("WireSyncClient")
@@ -208,7 +208,8 @@
 	// in the protocol.
 	Events []*Method
 
-	// Templated names for wire helper types.
+	// Generated struct holding variant-agnostic details about protocol.
+	ProtocolDetails Name
 }
 
 func (Protocol) Kind() declKind {
@@ -247,11 +248,12 @@
 	}
 
 	return Protocol{
-		protocolInner: inner,
-		OneWayMethods: filterBy(kinds{oneWayMethod}),
-		TwoWayMethods: filterBy(kinds{twoWayMethod}),
-		ClientMethods: filterBy(kinds{oneWayMethod, twoWayMethod}),
-		Events:        filterBy(kinds{eventMethod}),
+		protocolInner:   inner,
+		OneWayMethods:   filterBy(kinds{oneWayMethod}),
+		TwoWayMethods:   filterBy(kinds{twoWayMethod}),
+		ClientMethods:   filterBy(kinds{oneWayMethod, twoWayMethod}),
+		Events:          filterBy(kinds{eventMethod}),
+		ProtocolDetails: MakeName("fidl::internal::ProtocolDetails").Template(inner.Wire),
 	}
 }
 
diff --git a/zircon/system/ulib/c/test/debugdata.cc b/zircon/system/ulib/c/test/debugdata.cc
index 2fb787a..dc23bae 100644
--- a/zircon/system/ulib/c/test/debugdata.cc
+++ b/zircon/system/ulib/c/test/debugdata.cc
@@ -64,7 +64,7 @@
     auto node = fbl::MakeRefCounted<fs::Service>([dispatcher, this](zx::channel channel) {
       return fidl::BindSingleInFlightOnly(dispatcher, std::move(channel), this);
     });
-    dir->AddEntry(fuchsia_debugdata::DebugData::Name, node);
+    dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_debugdata::DebugData>, node);
 
     zx::channel server;
     ASSERT_OK(zx::channel::create(0, client, &server));
diff --git a/zircon/system/ulib/cobalt-client/cobalt_logger.cc b/zircon/system/ulib/cobalt-client/cobalt_logger.cc
index 5b28680..f3e528d 100644
--- a/zircon/system/ulib/cobalt-client/cobalt_logger.cc
+++ b/zircon/system/ulib/cobalt-client/cobalt_logger.cc
@@ -35,7 +35,9 @@
 
 }  // namespace
 
-std::string_view CobaltLogger::GetServiceName() { return fuchsia_cobalt::LoggerFactory::Name; }
+std::string_view CobaltLogger::GetServiceName() {
+  return fidl::DiscoverableProtocolName<fuchsia_cobalt::LoggerFactory>;
+}
 
 bool CobaltLogger::TryObtainLogger() {
   if (logger_.client_end().is_valid()) {
diff --git a/zircon/system/ulib/devmgr-integration-test/launcher.cc b/zircon/system/ulib/devmgr-integration-test/launcher.cc
index 47f40e2..62480a1 100644
--- a/zircon/system/ulib/devmgr-integration-test/launcher.cc
+++ b/zircon/system/ulib/devmgr-integration-test/launcher.cc
@@ -21,6 +21,7 @@
 #include <lib/fdio/fdio.h>
 #include <lib/fidl-async/bind.h>
 #include <lib/fidl-async/cpp/bind.h>
+#include <lib/fidl/llcpp/connect_service.h>
 #include <lib/service/llcpp/service.h>
 #include <lib/vfs/cpp/remote_dir.h>
 #include <lib/zx/exception.h>
@@ -128,7 +129,7 @@
       [dispatcher, server{std::move(server)}](fidl::ServerEnd<Protocol> channel) {
         return fidl::BindSingleInFlightOnly(dispatcher, std::move(channel), server.get());
       });
-  root->AddEntry(Protocol::Name, node);
+  root->AddEntry(fidl::DiscoverableProtocolName<Protocol>, node);
 }
 
 void CreateFakeService(fbl::RefPtr<fs::PseudoDir> root, const char* name,
diff --git a/zircon/system/ulib/fidl/include/lib/fidl/llcpp/connect_service.h b/zircon/system/ulib/fidl/include/lib/fidl/llcpp/connect_service.h
index ccbbe09..0a842c5 100644
--- a/zircon/system/ulib/fidl/include/lib/fidl/llcpp/connect_service.h
+++ b/zircon/system/ulib/fidl/include/lib/fidl/llcpp/connect_service.h
@@ -100,6 +100,36 @@
 
 #endif  // __Fuchsia__
 
+namespace internal {
+// This struct template is specialized in generated bindings to include the following
+// protocol-specific members:
+//  - static constexpr char DiscoverableName[] - the discoverable name if any exists.
+template <typename Protocol>
+struct ProtocolDetails;
+
+// Helper type for compile-time string concatenation.
+template <const char*, typename>
+struct default_service_path;
+template <const char* n, size_t... i>
+struct default_service_path<n, std::integer_sequence<size_t, i...>> {
+  static constexpr const char value[]{'/', 's', 'v', 'c', '/', n[i]...};
+};
+}  // namespace internal
+
+// DiscoverableProtocolName<Protocol> evaluates to a string containing the name of the protocol,
+// including its library.
+template <typename Protocol>
+constexpr const char* DiscoverableProtocolName =
+    fidl::internal::ProtocolDetails<Protocol>::DiscoverableName;
+
+// DiscoverableProtocolDefaultPath<Protocol> evaluates to a string containing the default path for
+// the protocol endpoint, something like "/svc/fuchsia.library.Protocol".
+template <typename Protocol>
+constexpr const char* DiscoverableProtocolDefaultPath = fidl::internal::default_service_path<
+    fidl::internal::ProtocolDetails<Protocol>::DiscoverableName,
+    std::make_integer_sequence<
+        size_t, sizeof(fidl::internal::ProtocolDetails<Protocol>::DiscoverableName)>>::value;
+
 }  // namespace fidl
 
 #endif  // LIB_FIDL_LLCPP_CONNECT_SERVICE_H_
diff --git a/zircon/system/ulib/runtests-utils/fuchsia-run-test.cc b/zircon/system/ulib/runtests-utils/fuchsia-run-test.cc
index 24d674d..c6ce78e 100644
--- a/zircon/system/ulib/runtests-utils/fuchsia-run-test.cc
+++ b/zircon/system/ulib/runtests-utils/fuchsia-run-test.cc
@@ -211,7 +211,7 @@
         [dispatcher = loop.dispatcher(), debug_data = debug_data.get()](zx::channel channel) {
           return fidl::BindSingleInFlightOnly(dispatcher, std::move(channel), debug_data);
         });
-    proxy_dir->AddEntry(fuchsia_debugdata::DebugData::Name, node);
+    proxy_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_debugdata::DebugData>, node);
 
     // Setup VFS.
     vfs = std::make_unique<fs::SynchronousVfs>(loop.dispatcher());
diff --git a/zircon/system/ulib/service/include/lib/service/llcpp/service.h b/zircon/system/ulib/service/include/lib/service/llcpp/service.h
index 96d0336..4732e4b 100644
--- a/zircon/system/ulib/service/include/lib/service/llcpp/service.h
+++ b/zircon/system/ulib/service/include/lib/service/llcpp/service.h
@@ -35,35 +35,6 @@
 // Implementation of |service::Clone| that is independent from the actual |Protocol|.
 ::zx::status<zx::channel> CloneRaw(::zx::unowned_channel&& node);
 
-template <size_t... I>
-using seq = std::integer_sequence<size_t, I...>;
-template <size_t N>
-using make_seq = std::make_integer_sequence<size_t, N>;
-
-template <const char*, typename, const char*, typename>
-struct concat;
-template <const char* s1, size_t... i1, const char* s2, size_t... i2>
-struct concat<s1, seq<i1...>, s2, seq<i2...>> {
-  // |s1| followed by |s2| followed by trailing NUL.
-  static constexpr const char value[]{s1[i1]..., s2[i2]..., 0};
-};
-
-template <size_t N>
-constexpr size_t string_length(const char (&literal)[N], size_t size = N - 1) {
-  return size;
-}
-
-// Returns the default path for a protocol in the `/svc/{name}` format,
-// where `{name}` is the fully qualified name of the FIDL protocol.
-// The string concatentation happens at compile time.
-template <typename Protocol>
-constexpr const char* DefaultPath() {
-  constexpr auto svc_length = string_length(llcpp::sys::kServiceDirectoryTrailingSlash);
-  constexpr auto protocol_length = string_length(Protocol::Name);
-  return concat<llcpp::sys::kServiceDirectoryTrailingSlash, make_seq<svc_length>, Protocol::Name,
-                make_seq<protocol_length>>::value;
-}
-
 // Determines if |Protocol| contains a method named |Clone|.
 // TODO(fxbug.dev/65964): This template is coupled to LLCPP codegen details,
 // and as such would need to be adapted when e.g. we change the LLCPP generated
@@ -118,7 +89,7 @@
 // See documentation on |fdio_service_connect| for details.
 template <typename Protocol>
 ::zx::status<::fidl::ClientEnd<Protocol>> Connect(
-    const char* path = internal::DefaultPath<Protocol>()) {
+    const char* path = fidl::DiscoverableProtocolDefaultPath<Protocol>) {
   auto channel = internal::ConnectRaw(path);
   if (channel.is_error()) {
     return channel.take_error();
@@ -136,7 +107,7 @@
 template <typename Protocol>
 ::zx::status<::fidl::ClientEnd<Protocol>> ConnectAt(
     ::fidl::UnownedClientEnd<fuchsia_io::Directory> svc_dir,
-    const char* protocol_name = Protocol::Name) {
+    const char* protocol_name = fidl::DiscoverableProtocolName<Protocol>) {
   auto channel = internal::ConnectAtRaw(svc_dir, protocol_name);
   if (channel.is_error()) {
     return channel.take_error();
diff --git a/zircon/system/ulib/test-utils/test-utils.cc b/zircon/system/ulib/test-utils/test-utils.cc
index 738eb93..4be403a 100644
--- a/zircon/system/ulib/test-utils/test-utils.cc
+++ b/zircon/system/ulib/test-utils/test-utils.cc
@@ -130,8 +130,8 @@
   status = zx::channel::create(0, &launcher_channel, &launcher_request);
   tu_check("creating channel for launcher service", status);
 
-  std::string service_name = "/svc/" + std::string(fprocess::Launcher::Name);
-  status = fdio_service_connect(service_name.c_str(), launcher_request.release());
+  status = fdio_service_connect(fidl::DiscoverableProtocolDefaultPath<fprocess::Launcher>,
+                                launcher_request.release());
   tu_check("connecting to launcher service", status);
 
   fidl::WireSyncClient<fprocess::Launcher> launcher(std::move(launcher_channel));
diff --git a/zircon/system/utest/miscsvc/main.cc b/zircon/system/utest/miscsvc/main.cc
index 1b8dbe8..10945f7 100644
--- a/zircon/system/utest/miscsvc/main.cc
+++ b/zircon/system/utest/miscsvc/main.cc
@@ -7,6 +7,7 @@
 #include <lib/fdio/directory.h>
 #include <lib/fdio/fd.h>
 #include <lib/fdio/fdio.h>
+#include <lib/fidl/llcpp/connect_service.h>
 #include <lib/zx/channel.h>
 #include <lib/zx/vmo.h>
 #include <zircon/status.h>
@@ -25,7 +26,8 @@
 
   zx::channel local, remote;
   ASSERT_OK(zx::channel::create(0, &local, &remote));
-  ASSERT_OK(fdio_service_connect_at(svc_local.get(), Paver::Name, remote.release()));
+  ASSERT_OK(fdio_service_connect_at(svc_local.get(), fidl::DiscoverableProtocolDefaultPath<Paver>,
+                                    remote.release()));
 
   zx::channel local2, remote2;
   ASSERT_OK(zx::channel::create(0, &local2, &remote2));
diff --git a/zircon/system/utest/service/llcpp/client_test.cc b/zircon/system/utest/service/llcpp/client_test.cc
index 23a7e1f..33194ff 100644
--- a/zircon/system/utest/service/llcpp/client_test.cc
+++ b/zircon/system/utest/service/llcpp/client_test.cc
@@ -180,21 +180,22 @@
 // Tests for connecting to singleton FIDL services (`/svc/MyProtocolName` style).
 //
 
-struct MockProtocol {
-  static constexpr char Name[] = "mock";
+struct MockProtocol {};
+
+template <>
+struct ::fidl::internal::ProtocolDetails<MockProtocol> {
+  static constexpr char DiscoverableName[] = "mock";
 };
 
 // Test compile time path concatenation.
 TEST(SingletonService, DefaultPath) {
-  static_assert(::service::internal::string_length(MockProtocol::Name) == 4);
-
-  constexpr auto path = ::service::internal::DefaultPath<MockProtocol>();
+  constexpr auto path = ::fidl::DiscoverableProtocolDefaultPath<MockProtocol>;
   ASSERT_STR_EQ(path, "/svc/mock", "protocol path should be /svc/mock");
 }
 
 // Using a local filesystem, test that |service::ConnectAt| successfully sends
-// an open request using the path |MockProtocol::Name|, when connecting to the
-// |MockProtocol| service.
+// an open request using the path |fidl::DiscoverableProtocolName<MockProtocol>|,
+// when connecting to the |MockProtocol| service.
 TEST(SingletonService, ConnectAt) {
   async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
   fs::SynchronousVfs vfs(loop.dispatcher());
@@ -207,7 +208,7 @@
     return ZX_OK;
   });
   auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
-  root_dir->AddEntry(MockProtocol::Name, std::move(protocol));
+  root_dir->AddEntry(fidl::DiscoverableProtocolName<MockProtocol>, std::move(protocol));
 
   auto directory = fidl::CreateEndpoints<fuchsia_io::Directory>();
   ASSERT_OK(directory.status_value());
diff --git a/zircon/system/utest/svchost/main.cc b/zircon/system/utest/svchost/main.cc
index 4bb5780..e7aa49f 100644
--- a/zircon/system/utest/svchost/main.cc
+++ b/zircon/system/utest/svchost/main.cc
@@ -154,7 +154,8 @@
   zx_status_t status = zx::channel::create(0, &client, &server);
   ASSERT_EQ(ZX_OK, status, "zx::channel::create failed");
 
-  fbl::String service_path = fbl::String::Concat({"/svc/", fuchsia_kernel::Stats::Name});
+  fbl::String service_path =
+      fbl::String::Concat({"/svc/", fidl::DiscoverableProtocolName<fuchsia_kernel::Stats>});
   status = fdio_service_connect(service_path.c_str(), server.release());
   ASSERT_EQ(ZX_OK, status, "fdio_service_connect failed");