diff --git a/src/objective-c/README.md b/src/objective-c/README.md
index 0e5eb9a25f666869c2d4f2d46a1d861e8234be34..e997b76d14ba145b806ee0c5e6ff267fd0e83939 100644
--- a/src/objective-c/README.md
+++ b/src/objective-c/README.md
@@ -163,7 +163,7 @@ files:
 
 * [Podspec](https://github.com/grpc/grpc/blob/master/gRPC.podspec) for the Objective-C gRPC runtime
 library. This can be tedious to configure manually.
-* [Podspec](https://github.com/jcanizales/protobuf/blob/add-podspec/Protobuf.podspec) for the
+* [Podspec](https://github.com/google/protobuf/blob/master/Protobuf.podspec) for the
 Objective-C Protobuf runtime library.
 
 [Protocol Buffers]:https://developers.google.com/protocol-buffers/
diff --git a/test/cpp/util/cli_call.cc b/test/cpp/util/cli_call.cc
index fa952e8349dff4ae9c95f3cb9612b19344bc4d30..83a7a1744a895035a5217f74c75bea9e672ec7ed 100644
--- a/test/cpp/util/cli_call.cc
+++ b/test/cpp/util/cli_call.cc
@@ -52,11 +52,20 @@ namespace {
 void* tag(int i) { return (void*)(gpr_intptr) i; }
 }  // namespace
 
-void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
-                   const grpc::string& method, const grpc::string& request,
-                   grpc::string* response) {
+Status CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
+                     const grpc::string& method, const grpc::string& request,
+                     grpc::string* response, const MetadataContainer& metadata,
+                     MetadataContainer* server_initial_metadata,
+                     MetadataContainer* server_trailing_metadata) {
   std::unique_ptr<grpc::GenericStub> stub(new grpc::GenericStub(channel));
   grpc::ClientContext ctx;
+  if (!metadata.empty()) {
+    for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
+             metadata.begin();
+         iter != metadata.end(); ++iter) {
+      ctx.AddMetadata(iter->first, iter->second);
+    }
+  }
   grpc::CompletionQueue cq;
   std::unique_ptr<grpc::GenericClientAsyncReaderWriter> call(
       stub->Call(&ctx, method, &cq, tag(1)));
@@ -79,7 +88,7 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
   cq.Next(&got_tag, &ok);
   if (!ok) {
     std::cout << "Failed to read response." << std::endl;
-    return;
+    return Status(StatusCode::INTERNAL, "Failed to read response");
   }
   grpc::Status status;
   call->Finish(&status, tag(5));
@@ -87,7 +96,6 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
   GPR_ASSERT(ok);
 
   if (status.ok()) {
-    std::cout << "RPC finished with OK status." << std::endl;
     std::vector<grpc::Slice> slices;
     recv_buffer.Dump(&slices);
 
@@ -96,10 +104,10 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
       response->append(reinterpret_cast<const char*>(slices[i].begin()),
                        slices[i].size());
     }
-  } else {
-    std::cout << "RPC finished with status code " << status.error_code()
-              << " details: " << status.error_message() << std::endl;
   }
+  *server_initial_metadata = ctx.GetServerInitialMetadata();
+  *server_trailing_metadata = ctx.GetServerTrailingMetadata();
+  return status;
 }
 
 }  // namespace testing
diff --git a/test/cpp/util/cli_call.h b/test/cpp/util/cli_call.h
index 7be8bb63c41846651eae2ca94861c618d4e87f73..8d114c9cb5ece4c5672630869170457247b366c7 100644
--- a/test/cpp/util/cli_call.h
+++ b/test/cpp/util/cli_call.h
@@ -34,17 +34,23 @@
 #ifndef GRPC_TEST_CPP_UTIL_CLI_CALL_H
 #define GRPC_TEST_CPP_UTIL_CLI_CALL_H
 
+#include <map>
+
 #include <grpc++/channel_interface.h>
 #include <grpc++/config.h>
+#include <grpc++/status.h>
 
 namespace grpc {
 namespace testing {
 
 class CliCall GRPC_FINAL {
  public:
-  static void Call(std::shared_ptr<grpc::ChannelInterface> channel,
-                   const grpc::string& method, const grpc::string& request,
-                   grpc::string* response);
+  typedef std::multimap<grpc::string, grpc::string> MetadataContainer;
+  static Status Call(std::shared_ptr<grpc::ChannelInterface> channel,
+                     const grpc::string& method, const grpc::string& request,
+                     grpc::string* response, const MetadataContainer& metadata,
+                     MetadataContainer* server_initial_metadata,
+                     MetadataContainer* server_trailing_metadata);
 };
 
 }  // namespace testing
diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc
index 12539c7479cb622cc922a7f6f53bf8cc18cc59e0..6cf86ea89bf5eb70703eb42997878b8b052564d3 100644
--- a/test/cpp/util/cli_call_test.cc
+++ b/test/cpp/util/cli_call_test.cc
@@ -60,6 +60,14 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
  public:
   Status Echo(ServerContext* context, const EchoRequest* request,
               EchoResponse* response) GRPC_OVERRIDE {
+    if (!context->client_metadata().empty()) {
+      for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
+               context->client_metadata().begin();
+           iter != context->client_metadata().end(); ++iter) {
+        context->AddInitialMetadata(iter->first, iter->second);
+      }
+    }
+    context->AddTrailingMetadata("trailing_key", "trailing_value");
     response->set_message(request->message());
     return Status::OK;
   }
@@ -106,6 +114,7 @@ TEST_F(CliCallTest, SimpleRpc) {
   request.set_message("Hello");
 
   ClientContext context;
+  context.AddMetadata("key1", "val1");
   Status s = stub_->Echo(&context, request, &response);
   EXPECT_EQ(response.message(), request.message());
   EXPECT_TRUE(s.ok());
@@ -114,8 +123,17 @@ TEST_F(CliCallTest, SimpleRpc) {
   grpc::string request_bin, response_bin, expected_response_bin;
   EXPECT_TRUE(request.SerializeToString(&request_bin));
   EXPECT_TRUE(response.SerializeToString(&expected_response_bin));
-  CliCall::Call(channel_, kMethod, request_bin, &response_bin);
+  std::multimap<grpc::string, grpc::string> client_metadata,
+      server_initial_metadata, server_trailing_metadata;
+  client_metadata.insert(std::pair<grpc::string, grpc::string>("key1", "val1"));
+  Status s2 = CliCall::Call(channel_, kMethod, request_bin, &response_bin,
+                            client_metadata, &server_initial_metadata,
+                            &server_trailing_metadata);
+  EXPECT_TRUE(s2.ok());
+
   EXPECT_EQ(expected_response_bin, response_bin);
+  EXPECT_EQ(context.GetServerInitialMetadata(), server_initial_metadata);
+  EXPECT_EQ(context.GetServerTrailingMetadata(), server_trailing_metadata);
 }
 
 }  // namespace testing
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index ad3c0af8775980577e42db833bbd356b2f23f358..32d61b03077c80a0e2fe56b951e676e2290f49e5 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -41,8 +41,8 @@
           body: "hello world"
         }
     b. under grpc/ run
-        protoc --proto_path=test/cpp/interop/ \
-        --encode=grpc.testing.SimpleRequest test/cpp/interop/messages.proto \
+        protoc --proto_path=test/proto/ \
+        --encode=grpc.testing.SimpleRequest test/proto/messages.proto \
         < input.txt > input.bin
   2. Start a server
     make interop_server && bins/opt/interop_server --port=50051
@@ -51,10 +51,12 @@
     /grpc.testing.TestService/UnaryCall --enable_ssl=false \
     --input_binary_file=input.bin --output_binary_file=output.bin
   4. Decode response
-    protoc --proto_path=test/cpp/interop/ \
-    --decode=grpc.testing.SimpleResponse test/cpp/interop/messages.proto \
+    protoc --proto_path=test/proto/ \
+    --decode=grpc.testing.SimpleResponse test/proto/messages.proto \
     < output.bin > output.txt
   5. Now the text form of response should be in output.txt
+  Optionally, metadata can be passed to server via flag --metadata, e.g.
+    --metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
 */
 
 #include <fstream>
@@ -77,6 +79,44 @@ DEFINE_string(input_binary_file, "",
               "Path to input file containing serialized request.");
 DEFINE_string(output_binary_file, "output.bin",
               "Path to output file to write serialized response.");
+DEFINE_string(metadata, "",
+              "Metadata to send to server, in the form of key1:val1:key2:val2");
+
+void ParseMetadataFlag(
+    std::multimap<grpc::string, grpc::string>* client_metadata) {
+  if (FLAGS_metadata.empty()) {
+    return;
+  }
+  std::vector<grpc::string> fields;
+  grpc::string delim(":");
+  size_t cur, next = -1;
+  do {
+    cur = next + 1;
+    next = FLAGS_metadata.find_first_of(delim, cur);
+    fields.push_back(FLAGS_metadata.substr(cur, next - cur));
+  } while (next != grpc::string::npos);
+  if (fields.size() % 2) {
+    std::cout << "Failed to parse metadata flag" << std::endl;
+    exit(1);
+  }
+  for (size_t i = 0; i < fields.size(); i += 2) {
+    client_metadata->insert(
+        std::pair<grpc::string, grpc::string>(fields[i], fields[i + 1]));
+  }
+}
+
+void PrintMetadata(const std::multimap<grpc::string, grpc::string>& m,
+                   const grpc::string& message) {
+  if (m.empty()) {
+    return;
+  }
+  std::cout << message << std::endl;
+  for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
+           m.begin();
+       iter != m.end(); ++iter) {
+    std::cout << iter->first << " : " << iter->second << std::endl;
+  }
+}
 
 int main(int argc, char** argv) {
   grpc::testing::InitTest(&argc, &argv, true);
@@ -118,11 +158,27 @@ int main(int argc, char** argv) {
       grpc::CreateChannel(server_address, creds, grpc::ChannelArguments());
 
   grpc::string response;
-  grpc::testing::CliCall::Call(channel, method, input_stream.str(), &response);
-  if (!response.empty()) {
-    std::ofstream output_file(FLAGS_output_binary_file,
-                              std::ios::trunc | std::ios::binary);
-    output_file << response;
+  std::multimap<grpc::string, grpc::string> client_metadata,
+      server_initial_metadata, server_trailing_metadata;
+  ParseMetadataFlag(&client_metadata);
+  PrintMetadata(client_metadata, "Sending client initial metadata:");
+  grpc::Status s = grpc::testing::CliCall::Call(
+      channel, method, input_stream.str(), &response, client_metadata,
+      &server_initial_metadata, &server_trailing_metadata);
+  PrintMetadata(server_initial_metadata,
+                "Received initial metadata from server:");
+  PrintMetadata(server_trailing_metadata,
+                "Received trailing metadata from server:");
+  if (s.ok()) {
+    std::cout << "Rpc succeeded with OK status" << std::endl;
+    if (!response.empty()) {
+      std::ofstream output_file(FLAGS_output_binary_file,
+                                std::ios::trunc | std::ios::binary);
+      output_file << response;
+    }
+  } else {
+    std::cout << "Rpc failed with status code " << s.error_code()
+              << " error message " << s.error_message() << std::endl;
   }
 
   return 0;