diff --git a/garnet/bin/component_index/BUILD.gn b/garnet/bin/component_index/BUILD.gn
index 7247d01db20989f6fe39ce5ea4e60b79280d1066..65c6f9e4eb0b3f122f739cf2f6a8144303b64137 100644
--- a/garnet/bin/component_index/BUILD.gn
+++ b/garnet/bin/component_index/BUILD.gn
@@ -2,8 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/fidl/fidl.gni")
 import("//build/package.gni")
 import("//build/rust/rustc_binary.gni")
+import("//build/test/test_package.gni")
+import("//build/testing/environments.gni")
 
 package("component_index") {
   testonly = true
@@ -24,7 +27,19 @@ package("component_index") {
 
 rustc_binary("component_index_bin") {
   name = "component_index"
+  with_unit_tests = true
   edition = "2018"
+
+  deps = [
+    "//garnet/bin/component_index/fidl:index-rustc",
+    "//garnet/public/lib/fidl/rust/fidl",
+    "//garnet/public/rust/fuchsia-async",
+    "//garnet/public/rust/fuchsia-component",
+    "//garnet/public/rust/fuchsia-runtime",
+    "//garnet/public/rust/fuchsia-zircon",
+    "//third_party/rust_crates:failure",
+    "//third_party/rust_crates:futures-preview",
+  ]
 }
 
 fuchsia_component("component_index_component") {
@@ -35,3 +50,17 @@ fuchsia_component("component_index_component") {
 
   binary = "component_index"
 }
+
+test_package("component_index_tests") {
+  deps = [
+    ":component_index_bin",
+  ]
+
+  tests = [
+    {
+      name = "component_index_bin_test"
+      dest = "component_index_tests"
+      environments = basic_envs
+    },
+  ]
+}
diff --git a/garnet/bin/component_index/meta/component_index_tests.cmx b/garnet/bin/component_index/meta/component_index_tests.cmx
new file mode 100644
index 0000000000000000000000000000000000000000..d0111340c9a650bbf7e241bd466ca431581ba317
--- /dev/null
+++ b/garnet/bin/component_index/meta/component_index_tests.cmx
@@ -0,0 +1,5 @@
+{
+    "program": {
+        "binary": "test/component_index_tests"
+    }
+}
diff --git a/garnet/bin/component_index/src/main.rs b/garnet/bin/component_index/src/main.rs
index 8b95e50c7ef449b84f28475a78416a7bee9c12f4..c9c9fba4e6afb52c5ddb79439ce8dcc36e5bd7a3 100644
--- a/garnet/bin/component_index/src/main.rs
+++ b/garnet/bin/component_index/src/main.rs
@@ -2,6 +2,109 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-fn main() {
-    // TODO(CF-162): Implement component index.
+#![feature(async_await, await_macro, futures_api)]
+
+use failure::{Error, ResultExt};
+use fidl_fuchsia_sys_index::{ComponentIndexRequest, ComponentIndexRequestStream};
+use fuchsia_async as fasync;
+use fuchsia_component::server::ServiceFs;
+use futures::prelude::*;
+use std::fs;
+use std::sync::Arc;
+
+async fn run_fuzzy_search_server(
+    mut stream: ComponentIndexRequestStream,
+    index: Arc<Vec<String>>,
+) -> Result<(), Error> {
+    while let Some(ComponentIndexRequest::FuzzySearch { needle, responder }) =
+        await!(stream.try_next()).context("Error serving fuzzy search")?
+    {
+        let mut ret = vec![];
+
+        if check_needle(&needle) {
+            let mut iter = index.iter();
+            while let Some(c) = iter.next() {
+                if c.contains(&needle) {
+                    ret.push(c.as_str());
+                }
+            }
+        }
+
+        responder.send(&mut ret.into_iter()).context("error sending response")?;
+    }
+    Ok(())
+}
+
+/// Needle only accepts a-zA-Z0-9 _ - /
+fn check_needle(needle: &str) -> bool {
+    return needle.chars().all(|c| c.is_alphanumeric() || c == '/' || c == '_' || c == '-');
+}
+
+enum IncomingServices {
+    ComponentIndex(ComponentIndexRequestStream),
+}
+
+#[fasync::run_singlethreaded]
+async fn main() -> Result<(), Error> {
+    let mut fs = ServiceFs::new_local();
+
+    let index_string = fs::read_to_string("/pkg/data/component_index.txt")
+        .expect("Error reading component_index.txt");
+    let index_vec: Vec<String> = index_string.lines().map(|l| l.to_string()).collect();
+    let index = Arc::new(index_vec);
+
+    fs.dir("public").add_fidl_service(IncomingServices::ComponentIndex);
+    fs.take_and_serve_directory_handle()?;
+
+    const MAX_CONCURRENT: usize = 10_000;
+    let fut = fs.for_each_concurrent(MAX_CONCURRENT, |IncomingServices::ComponentIndex(stream)| {
+        run_fuzzy_search_server(stream, index.clone()).unwrap_or_else(|e| println!("{:?}", e))
+    });
+    await!(fut);
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    macro_rules! test_check_needle {
+        (
+            $(
+                $test_name:ident => {
+                    needle = $fuzzy_needle:expr,
+                    accept = $fuzzy_accept:expr,
+                }
+            )+
+        ) => {
+            $(
+                mod $test_name {
+                    use super::*;
+                    #[test]
+                    fn test_eq() {
+                        assert_eq!(check_needle($fuzzy_needle), $fuzzy_accept);
+                    }
+                }
+            )+
+        }
+    }
+
+    test_check_needle! {
+        test_parse_alphanumeric => {
+            needle = "F00bar",
+            accept = true,
+        }
+        test_parse_dashes => {
+            needle = "foo_bar-baz",
+            accept = true,
+        }
+        test_parse_forward_slash => {
+            needle = "foo/bar",
+            accept = true,
+        }
+        test_parse_false => {
+            needle = "foo bar",
+            accept = false,
+        }
+    }
 }
diff --git a/garnet/packages/tests/BUILD.gn b/garnet/packages/tests/BUILD.gn
index 75c2347c8fb1ef576d96c37a2c7b9c52ff35cf73..aa0d3951b6d92789375aa4108c8b0bd5ffb8e4ee 100644
--- a/garnet/packages/tests/BUILD.gn
+++ b/garnet/packages/tests/BUILD.gn
@@ -289,6 +289,7 @@ group("all") {
     "//garnet/packages/tests:cmx",
     "//garnet/packages/tests:cobalt_client",
     "//garnet/packages/tests:component_cpp",
+    "//garnet/packages/tests:component_index",
     "//garnet/packages/tests:components_binary_test",
     "//garnet/packages/tests:containers_cpp",
     "//garnet/packages/tests:cpuperf",
@@ -1079,6 +1080,13 @@ group("run_test_component") {
   ]
 }
 
+group("component_index") {
+  testonly = true
+  public_deps = [
+    "//garnet/bin/component_index:component_index_tests",
+  ]
+}
+
 group("bluetooth") {
   testonly = true
   public_deps = [