diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index caa6220f2ccfecafc1140f1df21042535f4bb172..4eb542fae898bd3227599efe8f12e203de75da93 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -220,7 +220,7 @@ namespace Grpc.Core.Tests
             }
         }
 
-        private static async Task<string> EchoHandler(string request)
+        private static async Task<string> EchoHandler(ServerCallContext context, string request)
         {
             if (request == "THROW")
             {
@@ -229,7 +229,7 @@ namespace Grpc.Core.Tests
             return request;
         }
 
-        private static async Task<string> ConcatAndEchoHandler(IAsyncStreamReader<string> requestStream)
+        private static async Task<string> ConcatAndEchoHandler(ServerCallContext context, IAsyncStreamReader<string> requestStream)
         {
             string result = "";
             await requestStream.ForEach(async (request) =>
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 9c91541d904b3504bb143ced2566a1bb62f7697d..f5f2cf5f220e8f7dc44c38b3209832d456f2cb43 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -96,6 +96,7 @@
     <Compile Include="Internal\ServerResponseStream.cs" />
     <Compile Include="Internal\AtomicCounter.cs" />
     <Compile Include="Internal\DebugStats.cs" />
+    <Compile Include="ServerCallContext.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />
diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index 2bef6e68b7de064ac1a7469b987f9193949b8062..95d8e97869276aefd56d3243fb07819fd424cf07 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -74,7 +74,8 @@ namespace Grpc.Core.Internal
                 var request = await requestStream.ReadNext();
                 // TODO(jtattermusch): we need to read the full stream so that native callhandle gets deallocated.
                 Preconditions.CheckArgument(await requestStream.ReadNext() == null);
-                var result = await handler(request);
+                var context = new ServerCallContext();  // TODO(jtattermusch): initialize the context
+                var result = await handler(context, request);
                 await responseStream.Write(result);
             } 
             catch (Exception e)
@@ -125,7 +126,8 @@ namespace Grpc.Core.Internal
                 // TODO(jtattermusch): we need to read the full stream so that native callhandle gets deallocated.
                 Preconditions.CheckArgument(await requestStream.ReadNext() == null);
 
-                await handler(request, responseStream);
+                var context = new ServerCallContext();  // TODO(jtattermusch): initialize the context
+                await handler(context, request, responseStream);
             }
             catch (Exception e)
             {
@@ -168,11 +170,12 @@ namespace Grpc.Core.Internal
             var finishedTask = asyncCall.ServerSideCallAsync();
             var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
             var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
+            var context = new ServerCallContext();  // TODO(jtattermusch): initialize the context
 
             Status status = Status.DefaultSuccess;
             try
             {
-                var result = await handler(requestStream);
+                var result = await handler(context, requestStream);
                 try
                 {
                     await responseStream.Write(result);
@@ -223,11 +226,12 @@ namespace Grpc.Core.Internal
             var finishedTask = asyncCall.ServerSideCallAsync();
             var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
             var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
+            var context = new ServerCallContext();  // TODO(jtattermusch): initialize the context
 
             Status status = Status.DefaultSuccess;
             try
             {
-                await handler(requestStream, responseStream);
+                await handler(context, requestStream, responseStream);
             }
             catch (Exception e)
             {
diff --git a/src/csharp/Grpc.Core/ServerCallContext.cs b/src/csharp/Grpc.Core/ServerCallContext.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e873b3e88a74d0036737f7830e0726ac29a4b60c
--- /dev/null
+++ b/src/csharp/Grpc.Core/ServerCallContext.cs
@@ -0,0 +1,56 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+namespace Grpc.Core
+{
+    /// <summary>
+    /// Context for a server-side call.
+    /// </summary>
+    public sealed class ServerCallContext
+    {
+        
+        // TODO(jtattermusch): add cancellationToken
+
+        // TODO(jtattermusch): add deadline info
+
+        // TODO(jtattermusch): expose initial metadata sent by client for reading
+
+        // TODO(jtattermusch): expose method to send initial metadata back to client
+
+        // TODO(jtattermusch): allow setting status and trailing metadata to send after handler completes.
+    }
+}
diff --git a/src/csharp/Grpc.Core/ServerMethods.cs b/src/csharp/Grpc.Core/ServerMethods.cs
index 291835671f006f6e81e325a98680db564eaa641d..377b78eb302e5b1171fb87580855a1c87a75368a 100644
--- a/src/csharp/Grpc.Core/ServerMethods.cs
+++ b/src/csharp/Grpc.Core/ServerMethods.cs
@@ -42,28 +42,28 @@ namespace Grpc.Core
     /// <summary>
     /// Server-side handler for unary call.
     /// </summary>
-    public delegate Task<TResponse> UnaryServerMethod<TRequest, TResponse>(TRequest request)
+    public delegate Task<TResponse> UnaryServerMethod<TRequest, TResponse>(ServerCallContext context, TRequest request)
         where TRequest : class
         where TResponse : class;
 
     /// <summary>
     /// Server-side handler for client streaming call.
     /// </summary>
-    public delegate Task<TResponse> ClientStreamingServerMethod<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream)
+    public delegate Task<TResponse> ClientStreamingServerMethod<TRequest, TResponse>(ServerCallContext context, IAsyncStreamReader<TRequest> requestStream)
         where TRequest : class
         where TResponse : class;
 
     /// <summary>
     /// Server-side handler for server streaming call.
     /// </summary>
-    public delegate Task ServerStreamingServerMethod<TRequest, TResponse>(TRequest request, IServerStreamWriter<TResponse> responseStream)
+    public delegate Task ServerStreamingServerMethod<TRequest, TResponse>(ServerCallContext context, TRequest request, IServerStreamWriter<TResponse> responseStream)
         where TRequest : class
         where TResponse : class;
 
     /// <summary>
     /// Server-side handler for bidi streaming call.
     /// </summary>
-    public delegate Task DuplexStreamingServerMethod<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream)
+    public delegate Task DuplexStreamingServerMethod<TRequest, TResponse>(ServerCallContext context, IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream)
         where TRequest : class
         where TResponse : class;
 }
diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs
index 60408b901848e94be15f2d14021594c2bccf54d6..03f5c31cb7acc77e7c846f93e08daa3c9cad1847 100644
--- a/src/csharp/Grpc.Examples/MathGrpc.cs
+++ b/src/csharp/Grpc.Examples/MathGrpc.cs
@@ -133,13 +133,13 @@ namespace math
         // server-side interface
         public interface IMathService
         {
-            Task<DivReply> Div(DivArgs request);
+            Task<DivReply> Div(ServerCallContext context, DivArgs request);
 
-            Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream);
+            Task Fib(ServerCallContext context, FibArgs request, IServerStreamWriter<Num> responseStream);
 
-            Task<Num> Sum(IAsyncStreamReader<Num> requestStream);
+            Task<Num> Sum(ServerCallContext context, IAsyncStreamReader<Num> requestStream);
 
-            Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream);
+            Task DivMany(ServerCallContext context, IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream);
         }
 
         public static ServerServiceDefinition BindService(IMathService serviceImpl)
diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs
index 83ec2a8c3df20fcda82be12209088e0812adadc6..800dee8735412a037d76c831a9e953c042feff62 100644
--- a/src/csharp/Grpc.Examples/MathServiceImpl.cs
+++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs
@@ -46,12 +46,12 @@ namespace math
     /// </summary>
     public class MathServiceImpl : MathGrpc.IMathService
     {
-        public Task<DivReply> Div(DivArgs request)
+        public Task<DivReply> Div(ServerCallContext context, DivArgs request)
         {
             return Task.FromResult(DivInternal(request));
         }
 
-        public async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream)
+        public async Task Fib(ServerCallContext context, FibArgs request, IServerStreamWriter<Num> responseStream)
         {
             if (request.Limit <= 0)
             {
@@ -68,7 +68,7 @@ namespace math
             }
         }
 
-        public async Task<Num> Sum(IAsyncStreamReader<Num> requestStream)
+        public async Task<Num> Sum(ServerCallContext context, IAsyncStreamReader<Num> requestStream)
         {
             long sum = 0;
             await requestStream.ForEach(async num =>
@@ -78,7 +78,7 @@ namespace math
             return Num.CreateBuilder().SetNum_(sum).Build();
         }
 
-        public async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream)
+        public async Task DivMany(ServerCallContext context, IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream)
         {
             await requestStream.ForEach(async divArgs =>
             {
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
index d1f8aa12c78187f806a317ee455b5967f0f30f1e..9f14dad6c0c4e7170282743587bb27e723e5c9f1 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
@@ -171,17 +171,17 @@ namespace grpc.testing
         // server-side interface
         public interface ITestService
         {
-            Task<Empty> EmptyCall(Empty request);
+            Task<Empty> EmptyCall(ServerCallContext context, Empty request);
 
-            Task<SimpleResponse> UnaryCall(SimpleRequest request);
+            Task<SimpleResponse> UnaryCall(ServerCallContext context, SimpleRequest request);
 
-            Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
+            Task StreamingOutputCall(ServerCallContext context, StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
 
-            Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream);
+            Task<StreamingInputCallResponse> StreamingInputCall(ServerCallContext context, IAsyncStreamReader<StreamingInputCallRequest> requestStream);
 
-            Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
+            Task FullDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
 
-            Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
+            Task HalfDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
         }
 
         public static ServerServiceDefinition BindService(ITestService serviceImpl)
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
index 8b0cf3a2d0596c8319f8db6dfd77478701999071..40f32b5a88f0ad989d6416bdd0b8abd2fd4e8e07 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
@@ -46,19 +46,19 @@ namespace grpc.testing
     /// </summary>
     public class TestServiceImpl : TestServiceGrpc.ITestService
     {
-        public Task<Empty> EmptyCall(Empty request)
+        public Task<Empty> EmptyCall(ServerCallContext context, Empty request)
         {
             return Task.FromResult(Empty.DefaultInstance);
         }
 
-        public Task<SimpleResponse> UnaryCall(SimpleRequest request)
+        public Task<SimpleResponse> UnaryCall(ServerCallContext context, SimpleRequest request)
         {
             var response = SimpleResponse.CreateBuilder()
                 .SetPayload(CreateZerosPayload(request.ResponseSize)).Build();
             return Task.FromResult(response);
         }
 
-        public async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream)
+        public async Task StreamingOutputCall(ServerCallContext context, StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream)
         {
             foreach (var responseParam in request.ResponseParametersList)
             {
@@ -68,7 +68,7 @@ namespace grpc.testing
             }
         }
 
-        public async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream)
+        public async Task<StreamingInputCallResponse> StreamingInputCall(ServerCallContext context, IAsyncStreamReader<StreamingInputCallRequest> requestStream)
         {
             int sum = 0;
             await requestStream.ForEach(async request =>
@@ -78,7 +78,7 @@ namespace grpc.testing
             return StreamingInputCallResponse.CreateBuilder().SetAggregatedPayloadSize(sum).Build();
         }
 
-        public async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream)
+        public async Task FullDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream)
         {
             await requestStream.ForEach(async request =>
             {
@@ -91,7 +91,7 @@ namespace grpc.testing
             });
         }
 
-        public async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream)
+        public async Task HalfDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream)
         {
             throw new NotImplementedException();
         }