diff --git a/Makefile b/Makefile
index e156bc25a20d106b36f855da8f0d67f68d8754dc..37999d3b1e26e2a3faad9db4cd5c08c6076a51ed 100644
--- a/Makefile
+++ b/Makefile
@@ -4090,6 +4090,7 @@ endif
 LIBGRPC_CLI_LIBS_SRC = \
     test/cpp/util/cli_call.cc \
     test/cpp/util/proto_file_parser.cc \
+    test/cpp/util/proto_reflection_descriptor_database.cc \
 
 PUBLIC_HEADERS_CXX += \
 
@@ -10997,16 +10998,16 @@ $(BINDIR)/$(CONFIG)/grpc_cli: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/grpc_cli: $(PROTOBUF_DEP) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(BINDIR)/$(CONFIG)/grpc_cli: $(PROTOBUF_DEP) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_cli
+	$(Q) $(LDXX) $(LDFLAGS) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_cli
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_cli.o:  $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_cli.o:  $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_grpc_cli: $(GRPC_CLI_OBJS:.o=.dep)
 
@@ -14920,6 +14921,7 @@ test/cpp/util/byte_buffer_proto_helper.cc: $(OPENSSL_DEP)
 test/cpp/util/cli_call.cc: $(OPENSSL_DEP)
 test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP)
 test/cpp/util/proto_file_parser.cc: $(OPENSSL_DEP)
+test/cpp/util/proto_reflection_descriptor_database.cc: $(OPENSSL_DEP)
 test/cpp/util/string_ref_helper.cc: $(OPENSSL_DEP)
 test/cpp/util/subprocess.cc: $(OPENSSL_DEP)
 test/cpp/util/test_config.cc: $(OPENSSL_DEP)
diff --git a/build.yaml b/build.yaml
index 57545839d43e8aa93b238e982dbf776124b7fb99..237394c20569e3d7bbc49fc97d90c8c9ad2e49b8 100644
--- a/build.yaml
+++ b/build.yaml
@@ -1030,10 +1030,13 @@ libs:
   headers:
   - test/cpp/util/cli_call.h
   - test/cpp/util/proto_file_parser.h
+  - test/cpp/util/proto_reflection_descriptor_database.h
   src:
   - test/cpp/util/cli_call.cc
   - test/cpp/util/proto_file_parser.cc
+  - test/cpp/util/proto_reflection_descriptor_database.cc
   deps:
+  - grpc++_reflection
   - grpc++
   - grpc_plugin_support
 - name: grpc_plugin_support
@@ -2657,6 +2660,7 @@ targets:
   - grpc_cli_libs
   - grpc++_test_util
   - grpc_test_util
+  - grpc++_reflection
   - grpc++
   - grpc
   - gpr_test_util
diff --git a/doc/command_line_tool.md b/doc/command_line_tool.md
index 89a70548b8b23306e859b76794cf92c42a290a44..79a131c041a969bd4166d1b4e05a2a77bc8210e1 100644
--- a/doc/command_line_tool.md
+++ b/doc/command_line_tool.md
@@ -15,6 +15,7 @@ The command line tool can do the following things:
 - Send unary rpc.
 - Attach metadata and display received metadata.
 - Handle common authentication to server.
+- Infer request/response types from server reflection result.
 - Find the request/response types from a given proto file.
 - Read proto request in text form.
 - Read request in wire form (for protobuf messages, this means serialized binary form).
@@ -24,7 +25,6 @@ The command line tool can do the following things:
 The command line tool should support the following things:
 
 - List server services and methods through server reflection.
-- Infer request/response types from server reflection result.
 - Fine-grained auth control (such as, use this oauth token to talk to the server).
 - Send streaming rpc.
 
@@ -46,24 +46,35 @@ https://github.com/grpc/grpc/blob/master/test/cpp/util/grpc_cli.cc
 Send a rpc to a helloworld server at `localhost:50051`:
 
 ```
-$ bins/opt/grpc_cli call localhost:50051 SayHello examples/protos/helloworld.proto \
-    "name: 'world'"  --enable_ssl=false
+$ bins/opt/grpc_cli call localhost:50051 SayHello "name: 'world'" \
+    --enable_ssl=false
 ```
 
 On success, the tool will print out
 
 ```
 Rpc succeeded with OK status
-Response: 
+Response:
  message: "Hello world"
 ```
 
 The `localhost:50051` part indicates the server you are connecting to. `SayHello` is (part of) the
-gRPC method string. Then there is the path to the proto file containing the service definition,
-if it is not under current directory, you can use `--proto_path` to specify a new search root.
-`"name: 'world'"` is the text format of the request proto message. 
-We are not using ssl here by `--enable_ssl=false`. For information on more
-flags, look at the comments of `grpc_cli.cc`.
+gRPC method string. Then `"name: 'world'"` is the text format of the request proto message. We are
+not using ssl here by `--enable_ssl=false`. For information on more flags, look at the comments of `grpc_cli.cc`.
+
+### Use local proto files
+
+If the server does not have the server reflection service, you will need to provide local proto
+files containing the service definition. The tool will try to find request/response types from
+them.
+
+```
+$ bins/opt/grpc_cli call localhost:50051 SayHello "name: 'world'" \
+    --protofiles=examples/protos/helloworld.proto --enable_ssl=false
+```
+
+If the proto files is not under current directory, you can use `--proto_path` to specify a new
+search root.
 
 ### Send non-proto rpc
 
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index c52e48bae650c1b5502de335473677a2ad80030a..53529da782ce1380968ba7c1b74f0afec38a47db 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -34,18 +34,21 @@
 /*
   A command line tool to talk to a grpc server.
   Example of talking to grpc interop server:
-  grpc_cli call localhost:50051 UnaryCall src/proto/grpc/testing/test.proto \
-    "response_size:10"  --enable_ssl=false
+  grpc_cli call localhost:50051 UnaryCall "response_size:10" \
+      --protofiles=src/proto/grpc/testing/test.proto --enable_ssl=false
 
   Options:
-    1. --proto_path, if your proto file is not under current working directory,
+    1. --protofiles, use this flag to provide a proto file if the server does
+       does not have the reflection service.
+    2. --proto_path, if your proto file is not under current working directory,
        use this flag to provide a search root. It should work similar to the
-       counterpart in protoc.
-    2. --metadata specifies metadata to be sent to the server, such as:
+       counterpart in protoc. This option is valid only when protofiles is
+       provided.
+    3. --metadata specifies metadata to be sent to the server, such as:
        --metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
-    3. --enable_ssl, whether to use tls.
-    4. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call
-    3. --input_binary_file, a file containing the serialized request. The file
+    4. --enable_ssl, whether to use tls.
+    5. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call
+    6. --input_binary_file, a file containing the serialized request. The file
        can be generated by calling something like:
        protoc --proto_path=src/proto/grpc/testing/ \
          --encode=grpc.testing.SimpleRequest \
@@ -53,7 +56,7 @@
          < input.txt > input.bin
        If this is used and no proto file is provided in the argument list, the
        method string has to be exact in the form of /package.service/method.
-    4. --output_binary_file, a file to write binary format response into, it can
+    7. --output_binary_file, a file to write binary format response into, it can
        be later decoded using protoc:
        protoc --proto_path=src/proto/grpc/testing/ \
        --decode=grpc.testing.SimpleResponse \
@@ -61,6 +64,7 @@
        < output.bin > output.txt
 */
 
+#include <unistd.h>
 #include <fstream>
 #include <iostream>
 #include <sstream>
@@ -86,6 +90,8 @@ DEFINE_string(output_binary_file, "",
 DEFINE_string(metadata, "",
               "Metadata to send to server, in the form of key1:val1:key2:val2");
 DEFINE_string(proto_path, ".", "Path to look for the proto file.");
+// TODO(zyc): support a list of input proto files
+DEFINE_string(protofiles, "", "Name of the proto file.");
 
 void ParseMetadataFlag(
     std::multimap<grpc::string, grpc::string>* client_metadata) {
@@ -129,35 +135,61 @@ void PrintMetadata(const T& m, const grpc::string& message) {
 int main(int argc, char** argv) {
   grpc::testing::InitTest(&argc, &argv, true);
 
-  if (argc < 4 || argc == 5 || grpc::string(argv[1]) != "call") {
+  if (argc < 4 || grpc::string(argv[1]) != "call") {
     std::cout << "Usage: grpc_cli call server_host:port method_name "
               << "[proto file] [text format request] [<options>]" << std::endl;
+    return 1;
   }
 
-  grpc::string file_name;
   grpc::string request_text;
   grpc::string server_address(argv[2]);
   grpc::string method_name(argv[3]);
   std::unique_ptr<grpc::testing::ProtoFileParser> parser;
   grpc::string serialized_request_proto;
 
-  if (argc == 6) {
-    file_name = argv[4];
-    // TODO(yangg) read from stdin as well?
-    request_text = argv[5];
+  if (argc == 5) {
+    request_text = argv[4];
+  }
+
+  std::shared_ptr<grpc::ChannelCredentials> creds;
+  if (!FLAGS_enable_ssl) {
+    creds = grpc::InsecureChannelCredentials();
+  } else {
+    if (FLAGS_use_auth) {
+      creds = grpc::GoogleDefaultCredentials();
+    } else {
+      creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
+    }
   }
+  std::shared_ptr<grpc::Channel> channel =
+      grpc::CreateChannel(server_address, creds);
 
   if (request_text.empty() && FLAGS_input_binary_file.empty()) {
-    std::cout << "Missing input. Use text format input or "
-              << "--input_binary_file for serialized request" << std::endl;
-    return 1;
-  } else if (!request_text.empty()) {
-    parser.reset(new grpc::testing::ProtoFileParser(FLAGS_proto_path, file_name,
-                                                    method_name));
+    if (isatty(STDIN_FILENO)) {
+      std::cout << "reading request message from stdin..." << std::endl;
+    }
+    std::stringstream input_stream;
+    input_stream << std::cin.rdbuf();
+    request_text = input_stream.str();
+  }
+
+  if (!request_text.empty()) {
+    if (!FLAGS_protofiles.empty()) {
+      parser.reset(new grpc::testing::ProtoFileParser(
+          FLAGS_proto_path, FLAGS_protofiles, method_name));
+    } else {
+      parser.reset(new grpc::testing::ProtoFileParser(channel, method_name));
+    }
     method_name = parser->GetFullMethodName();
     if (parser->HasError()) {
       return 1;
     }
+
+    if (!FLAGS_input_binary_file.empty()) {
+      std::cout
+          << "warning: request given in argv, ignoring --input_binary_file"
+          << std::endl;
+    }
   }
 
   if (parser) {
@@ -175,19 +207,6 @@ int main(int argc, char** argv) {
   }
   std::cout << "connecting to " << server_address << std::endl;
 
-  std::shared_ptr<grpc::ChannelCredentials> creds;
-  if (!FLAGS_enable_ssl) {
-    creds = grpc::InsecureChannelCredentials();
-  } else {
-    if (FLAGS_use_auth) {
-      creds = grpc::GoogleDefaultCredentials();
-    } else {
-      creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
-    }
-  }
-  std::shared_ptr<grpc::Channel> channel =
-      grpc::CreateChannel(server_address, creds);
-
   grpc::string serialized_response_proto;
   std::multimap<grpc::string, grpc::string> client_metadata;
   std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
@@ -219,7 +238,7 @@ int main(int argc, char** argv) {
     }
   } else {
     std::cout << "Rpc failed with status code " << s.error_code()
-              << " error message " << s.error_message() << std::endl;
+              << ", error message: " << s.error_message() << std::endl;
   }
 
   return 0;
diff --git a/test/cpp/util/proto_file_parser.cc b/test/cpp/util/proto_file_parser.cc
index 25aec329eb30e4e1cf40caeeaa4745eb7c5b5086..5b0d925e1c388ff4f8dea101873be2aeb0317dbf 100644
--- a/test/cpp/util/proto_file_parser.cc
+++ b/test/cpp/util/proto_file_parser.cc
@@ -95,9 +95,48 @@ ProtoFileParser::ProtoFileParser(const grpc::string& proto_path,
   dynamic_factory_.reset(
       new google::protobuf::DynamicMessageFactory(importer_->pool()));
 
+  std::vector<const google::protobuf::ServiceDescriptor*> service_desc_list;
+  for (int i = 0; i < file_desc->service_count(); i++) {
+    service_desc_list.push_back(file_desc->service(i));
+  }
+  InitProtoFileParser(method, service_desc_list);
+}
+
+ProtoFileParser::ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
+                                 const grpc::string& method)
+    : has_error_(false),
+      desc_db_(new grpc::ProtoReflectionDescriptorDatabase(channel)),
+      desc_pool_(new google::protobuf::DescriptorPool(desc_db_.get())) {
+  std::vector<std::string> service_list;
+  if (!desc_db_->GetServices(&service_list)) {
+    LogError(
+        "Failed to get services from the server, "
+        "it may not have the reflection service.\n"
+        "Please try to use the --protofiles option to provide a proto file.");
+  }
+  if (has_error_) {
+    return;
+  }
+  dynamic_factory_.reset(
+      new google::protobuf::DynamicMessageFactory(desc_pool_.get()));
+
+  std::vector<const google::protobuf::ServiceDescriptor*> service_desc_list;
+  for (auto it = service_list.begin(); it != service_list.end(); it++) {
+    service_desc_list.push_back(desc_pool_->FindServiceByName(*it));
+  }
+  InitProtoFileParser(method, service_desc_list);
+}
+
+ProtoFileParser::~ProtoFileParser() {}
+
+void ProtoFileParser::InitProtoFileParser(
+    const grpc::string& method,
+    const std::vector<const google::protobuf::ServiceDescriptor*>
+        service_desc_list) {
   const google::protobuf::MethodDescriptor* method_descriptor = nullptr;
-  for (int i = 0; !method_descriptor && i < file_desc->service_count(); i++) {
-    const auto* service_desc = file_desc->service(i);
+  for (auto it = service_desc_list.begin(); it != service_desc_list.end();
+       it++) {
+    const auto* service_desc = *it;
     for (int j = 0; j < service_desc->method_count(); j++) {
       const auto* method_desc = service_desc->method(j);
       if (MethodNameMatch(method_desc->full_name(), method)) {
@@ -130,8 +169,6 @@ ProtoFileParser::ProtoFileParser(const grpc::string& proto_path,
       dynamic_factory_->GetPrototype(method_descriptor->output_type())->New());
 }
 
-ProtoFileParser::~ProtoFileParser() {}
-
 grpc::string ProtoFileParser::GetSerializedProto(
     const grpc::string& text_format_proto, bool is_request) {
   grpc::string serialized;
@@ -143,7 +180,7 @@ grpc::string ProtoFileParser::GetSerializedProto(
     LogError("Failed to parse text format to proto.");
     return "";
   }
-  ok = request_prototype_->SerializeToString(&serialized);
+  ok = msg->SerializeToString(&serialized);
   if (!ok) {
     LogError("Failed to serialize proto.");
     return "";
diff --git a/test/cpp/util/proto_file_parser.h b/test/cpp/util/proto_file_parser.h
index 46cdd6650386d30483c9ba44bf0eb1a9fad34ed1..b442d77db9846ea04a15cba80d61a989e03ba444 100644
--- a/test/cpp/util/proto_file_parser.h
+++ b/test/cpp/util/proto_file_parser.h
@@ -38,8 +38,10 @@
 
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/dynamic_message.h>
+#include <grpc++/channel.h>
 
 #include "src/compiler/config.h"
+#include "test/cpp/util/proto_reflection_descriptor_database.h"
 
 namespace grpc {
 namespace testing {
@@ -53,6 +55,9 @@ class ProtoFileParser {
   // even just Method. It will log an error if there is ambiguity.
   ProtoFileParser(const grpc::string& proto_path, const grpc::string& file_name,
                   const grpc::string& method);
+
+  ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
+                  const grpc::string& method);
   ~ProtoFileParser();
 
   grpc::string GetFullMethodName() const { return full_method_name_; }
@@ -68,12 +73,18 @@ class ProtoFileParser {
   void LogError(const grpc::string& error_msg);
 
  private:
+  void InitProtoFileParser(
+      const grpc::string& method,
+      const std::vector<const google::protobuf::ServiceDescriptor*> services);
+
   bool has_error_;
   grpc::string request_text_;
   grpc::string full_method_name_;
   google::protobuf::compiler::DiskSourceTree source_tree_;
   std::unique_ptr<ErrorPrinter> error_printer_;
   std::unique_ptr<google::protobuf::compiler::Importer> importer_;
+  std::unique_ptr<grpc::ProtoReflectionDescriptorDatabase> desc_db_;
+  std::unique_ptr<google::protobuf::DescriptorPool> desc_pool_;
   std::unique_ptr<google::protobuf::DynamicMessageFactory> dynamic_factory_;
   std::unique_ptr<grpc::protobuf::Message> request_prototype_;
   std::unique_ptr<grpc::protobuf::Message> response_prototype_;
diff --git a/test/cpp/util/proto_reflection_descriptor_database.cc b/test/cpp/util/proto_reflection_descriptor_database.cc
index 25b720aee0a3697605d4a7b4f70fe3b798994d66..2d847012a22d908dd6b7ef86725254a1f1f0a666 100644
--- a/test/cpp/util/proto_reflection_descriptor_database.cc
+++ b/test/cpp/util/proto_reflection_descriptor_database.cc
@@ -53,7 +53,17 @@ ProtoReflectionDescriptorDatabase::ProtoReflectionDescriptorDatabase(
     std::shared_ptr<grpc::Channel> channel)
     : stub_(ServerReflection::NewStub(channel)) {}
 
-ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() {}
+ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() {
+  if (stream_) {
+    stream_->WritesDone();
+    Status status = stream_->Finish();
+    if (!status.ok()) {
+      gpr_log(GPR_ERROR,
+              "ServerReflectionInfo rpc failed. Error code: %d, details: %s",
+              (int)status.error_code(), status.error_message().c_str());
+    }
+  }
+}
 
 bool ProtoReflectionDescriptorDatabase::FindFileByName(
     const string& filename, google::protobuf::FileDescriptorProto* output) {
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index e3cfd55cd62f1bde7da7ff202fd68b7900082a47..4a27a1d87524b22bcc05f32d55fd853a3c8199ba 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -2133,6 +2133,7 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
+      "grpc++_reflection", 
       "grpc++_test_config", 
       "grpc++_test_util", 
       "grpc_cli_libs", 
@@ -4460,11 +4461,13 @@
   {
     "deps": [
       "grpc++", 
+      "grpc++_reflection", 
       "grpc_plugin_support"
     ], 
     "headers": [
       "test/cpp/util/cli_call.h", 
-      "test/cpp/util/proto_file_parser.h"
+      "test/cpp/util/proto_file_parser.h", 
+      "test/cpp/util/proto_reflection_descriptor_database.h"
     ], 
     "language": "c++", 
     "name": "grpc_cli_libs", 
@@ -4472,7 +4475,9 @@
       "test/cpp/util/cli_call.cc", 
       "test/cpp/util/cli_call.h", 
       "test/cpp/util/proto_file_parser.cc", 
-      "test/cpp/util/proto_file_parser.h"
+      "test/cpp/util/proto_file_parser.h", 
+      "test/cpp/util/proto_reflection_descriptor_database.cc", 
+      "test/cpp/util/proto_reflection_descriptor_database.h"
     ], 
     "third_party": false, 
     "type": "lib"
diff --git a/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj b/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj
index 39cb1e0cb58554a6ec3beb7cc97405ec4d4e67f2..d25c692e3e8128c1bb38af549e8445caa6615581 100644
--- a/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj
+++ b/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj
@@ -149,14 +149,20 @@
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h" />
     <ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_call.cc">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.cc">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_reflection\grpc++_reflection.vcxproj">
+      <Project>{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}</Project>
+    </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
       <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
     </ProjectReference>
diff --git a/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters b/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters
index 55ef18bf3061a883b39a9a1f34dbd16fa005c0fb..4add8ed5e13ee86b80c606083a66578d95d15aac 100644
--- a/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters
@@ -7,6 +7,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc">
       <Filter>test\cpp\util</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.cc">
+      <Filter>test\cpp\util</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h">
@@ -15,6 +18,9 @@
     <ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h">
       <Filter>test\cpp\util</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.h">
+      <Filter>test\cpp\util</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj b/vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj
index cd844d1579430e7a42c4089edd9fee80119b173e..9c8cdc54c2506b8e687bd7393d91d94073d485e4 100644
--- a/vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj
+++ b/vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj
@@ -173,6 +173,9 @@
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
       <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
     </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_reflection\grpc++_reflection.vcxproj">
+      <Project>{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}</Project>
+    </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
       <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
     </ProjectReference>