diff --git a/pkg/images/mocks/Images.go b/pkg/images/mocks/Images.go
new file mode 100644
index 0000000000000000000000000000000000000000..250fa5d0b8ef4c0a6993c2a318bea8f82cd24e6a
--- /dev/null
+++ b/pkg/images/mocks/Images.go
@@ -0,0 +1,39 @@
+// Code generated by mockery v2.7.4. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	files "git.perx.ru/perxis/perxis-go/pkg/files"
+	images "git.perx.ru/perxis/perxis-go/pkg/images"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// Images is an autogenerated mock type for the Images type
+type Images struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, source, opts
+func (_m *Images) Get(ctx context.Context, source *files.File, opts *images.GetOptions) (*files.File, error) {
+	ret := _m.Called(ctx, source, opts)
+
+	var r0 *files.File
+	if rf, ok := ret.Get(0).(func(context.Context, *files.File, *images.GetOptions) *files.File); ok {
+		r0 = rf(ctx, source, opts)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.File)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *files.File, *images.GetOptions) error); ok {
+		r1 = rf(ctx, source, opts)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
diff --git a/pkg/images/service.go b/pkg/images/service.go
new file mode 100644
index 0000000000000000000000000000000000000000..0162a58d32899eb8722273664f350006dad3553a
--- /dev/null
+++ b/pkg/images/service.go
@@ -0,0 +1,32 @@
+package images
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/files"
+)
+
+// Images - описывает интерфейс сервиса для обработки изображений
+// @microgen grpc
+// @protobuf git.perx.ru/perxis/perxis-go/proto/images
+type Images interface {
+
+	// Get - к файлу, идентификатор которого передан в запросе, применяются параметры.
+	// Может быть передано несколько параметров, порядок учитывается при обработке
+	// Допустимые операции:
+	//  - crop (ширина, высота)
+	//  - fit (ширина, высота)
+	//  - resize (ширина, высота)
+	//  - format (один из форматов [ png, jpeg, jpg, gif ]
+	// Возвращает объект File с заполненным полем File.URL
+	Get(ctx context.Context, source *files.File, opts *GetOptions) (result *files.File, err error)
+}
+
+type GetOptions struct {
+	Params []*Param
+}
+
+type Param struct {
+	Op    string
+	Value []string
+}
diff --git a/pkg/images/transport/client.microgen.go b/pkg/images/transport/client.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..9994b2c34e5234a20ae8d13846e3b5ef6fe41668
--- /dev/null
+++ b/pkg/images/transport/client.microgen.go
@@ -0,0 +1,28 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	"context"
+	"errors"
+
+	files "git.perx.ru/perxis/perxis-go/pkg/files"
+	images "git.perx.ru/perxis/perxis-go/pkg/images"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+func (set EndpointsSet) Get(arg0 context.Context, arg1 *files.File, arg2 *images.GetOptions) (res0 *files.File, res1 error) {
+	request := GetRequest{
+		Opts:   arg2,
+		Source: arg1,
+	}
+	response, res1 := set.GetEndpoint(arg0, &request)
+	if res1 != nil {
+		if e, ok := status.FromError(res1); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res1 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*GetResponse).Result, res1
+}
diff --git a/pkg/images/transport/endpoints.microgen.go b/pkg/images/transport/endpoints.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..21d3b27a337a434bab31a3026f6d5f6356d6b586
--- /dev/null
+++ b/pkg/images/transport/endpoints.microgen.go
@@ -0,0 +1,10 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import endpoint "github.com/go-kit/kit/endpoint"
+
+// EndpointsSet implements Images API and used for transport purposes.
+type EndpointsSet struct {
+	GetEndpoint endpoint.Endpoint
+}
diff --git a/pkg/images/transport/exchanges.microgen.go b/pkg/images/transport/exchanges.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..9b9992a01ee5d21e24a69a88731de706e35a846e
--- /dev/null
+++ b/pkg/images/transport/exchanges.microgen.go
@@ -0,0 +1,18 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	files "git.perx.ru/perxis/perxis-go/pkg/files"
+	images "git.perx.ru/perxis/perxis-go/pkg/images"
+)
+
+type (
+	GetRequest struct {
+		Source *files.File        `json:"source"`
+		Opts   *images.GetOptions `json:"opts"`
+	}
+	GetResponse struct {
+		Result *files.File `json:"result"`
+	}
+)
diff --git a/pkg/images/transport/grpc/client.microgen.go b/pkg/images/transport/grpc/client.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..5f104716e75e723e1d1ef7f784a085e8a6ad55d2
--- /dev/null
+++ b/pkg/images/transport/grpc/client.microgen.go
@@ -0,0 +1,20 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transportgrpc
+
+import (
+	transport "git.perx.ru/perxis/perxis-go/pkg/images/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/images"
+	grpckit "github.com/go-kit/kit/transport/grpc"
+	grpc "google.golang.org/grpc"
+)
+
+func NewGRPCClient(conn *grpc.ClientConn, addr string, opts ...grpckit.ClientOption) transport.EndpointsSet {
+	return transport.EndpointsSet{GetEndpoint: grpckit.NewClient(
+		conn, addr, "Get",
+		_Encode_Get_Request,
+		_Decode_Get_Response,
+		pb.GetResponse{},
+		opts...,
+	).Endpoint()}
+}
diff --git a/pkg/images/transport/grpc/protobuf_endpoint_converters.microgen.go b/pkg/images/transport/grpc/protobuf_endpoint_converters.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..e1800e1747d2d03335586a358e3139154b3ae0f0
--- /dev/null
+++ b/pkg/images/transport/grpc/protobuf_endpoint_converters.microgen.go
@@ -0,0 +1,74 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+// Please, do not change functions names!
+package transportgrpc
+
+import (
+	"context"
+	"errors"
+
+	transport "git.perx.ru/perxis/perxis-go/pkg/images/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/images"
+)
+
+func _Encode_Get_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetRequest")
+	}
+	req := request.(*transport.GetRequest)
+	reqSource, err := PtrFileFileToProto(req.Source)
+	if err != nil {
+		return nil, err
+	}
+	reqOpts, err := PtrGetOptionsToProto(req.Opts)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.GetRequest{
+		Opts:   reqOpts,
+		Source: reqSource,
+	}, nil
+}
+
+func _Encode_Get_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetResponse")
+	}
+	resp := response.(*transport.GetResponse)
+	respResult, err := PtrFileFileToProto(resp.Result)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.GetResponse{Result: respResult}, nil
+}
+
+func _Decode_Get_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetRequest")
+	}
+	req := request.(*pb.GetRequest)
+	reqSource, err := ProtoToPtrFileFile(req.Source)
+	if err != nil {
+		return nil, err
+	}
+	reqOpts, err := ProtoToPtrGetOptions(req.Opts)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.GetRequest{
+		Opts:   reqOpts,
+		Source: reqSource,
+	}, nil
+}
+
+func _Decode_Get_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetResponse")
+	}
+	resp := response.(*pb.GetResponse)
+	respResult, err := ProtoToPtrFileFile(resp.Result)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.GetResponse{Result: respResult}, nil
+}
diff --git a/pkg/images/transport/grpc/protobuf_type_converters.microgen.go b/pkg/images/transport/grpc/protobuf_type_converters.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..ff8c72337ca3dffda4433a785163c141e37967d7
--- /dev/null
+++ b/pkg/images/transport/grpc/protobuf_type_converters.microgen.go
@@ -0,0 +1,82 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+// It is better for you if you do not change functions names!
+// This files will never be overwritten.
+package transportgrpc
+
+import (
+	file "git.perx.ru/perxis/perxis-go/pkg/files"
+	service "git.perx.ru/perxis/perxis-go/pkg/images"
+	pbfile "git.perx.ru/perxis/perxis-go/proto/files"
+	pbimage "git.perx.ru/perxis/perxis-go/proto/images"
+)
+
+func PtrFileFileToProto(source *file.File) (*pbfile.File, error) {
+	if source == nil {
+		return nil, nil
+	}
+	pbFile := &pbfile.File{
+		Id:       source.ID,
+		Name:     source.Name,
+		Size:     int32(source.Size),
+		MimeType: source.MimeType,
+		Url:      source.URL,
+	}
+	return pbFile, nil
+}
+
+func ProtoToPtrFileFile(protoSource *pbfile.File) (*file.File, error) {
+	if protoSource == nil {
+		return nil, nil
+	}
+	file := &file.File{
+		ID:       protoSource.Id,
+		Name:     protoSource.Name,
+		Size:     int(protoSource.Size),
+		MimeType: protoSource.MimeType,
+		URL:      protoSource.Url,
+	}
+	return file, nil
+}
+
+func PtrGetOptionsToProto(opts *service.GetOptions) (*pbimage.GetRequest_GetOptions, error) {
+	if opts == nil {
+		return nil, nil
+	}
+
+	params := make([]*pbimage.Param, 0, len(opts.Params))
+
+	for _, p := range opts.Params {
+		params = append(params, &pbimage.Param{
+			Op:    p.Op,
+			Value: p.Value,
+		})
+	}
+
+	return &pbimage.GetRequest_GetOptions{Params: params}, nil
+}
+
+func ProtoToPtrGetOptions(protoOpts *pbimage.GetRequest_GetOptions) (*service.GetOptions, error) {
+	if protoOpts == nil {
+		return nil, nil
+	}
+
+	params := make([]*service.Param, 0, len(protoOpts.Params))
+
+	for _, p := range protoOpts.Params {
+		params = append(params, &service.Param{
+			Op:    p.Op,
+			Value: p.Value,
+		})
+	}
+
+	return &service.GetOptions{Params: params}, nil
+}
+
+//func PtrFilesFileToProto(source *files.File) (*pbimage.File, error) {
+//	panic("function not provided") // TODO: provide converter
+//}
+//
+//func ProtoToPtrFilesFile(protoSource *images.File) (*files.File, error) {
+//	panic("function not provided") // TODO: provide converter
+//}
diff --git a/pkg/images/transport/grpc/server.microgen.go b/pkg/images/transport/grpc/server.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..47e04dc3e59277209f7c6ff3b4028a8cf079d9e0
--- /dev/null
+++ b/pkg/images/transport/grpc/server.microgen.go
@@ -0,0 +1,34 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+// DO NOT EDIT.
+package transportgrpc
+
+import (
+	transport "git.perx.ru/perxis/perxis-go/pkg/images/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/images"
+	grpc "github.com/go-kit/kit/transport/grpc"
+	context "golang.org/x/net/context"
+)
+
+type imagesServer struct {
+	get grpc.Handler
+
+	pb.UnimplementedImagesServer
+}
+
+func NewGRPCServer(endpoints *transport.EndpointsSet, opts ...grpc.ServerOption) pb.ImagesServer {
+	return &imagesServer{get: grpc.NewServer(
+		endpoints.GetEndpoint,
+		_Decode_Get_Request,
+		_Encode_Get_Response,
+		opts...,
+	)}
+}
+
+func (S *imagesServer) Get(ctx context.Context, req *pb.GetRequest) (*pb.GetResponse, error) {
+	_, resp, err := S.get.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.GetResponse), nil
+}
diff --git a/pkg/images/transport/server.microgen.go b/pkg/images/transport/server.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..26105401a1f079c3837d311ccf7da233c2deb9a7
--- /dev/null
+++ b/pkg/images/transport/server.microgen.go
@@ -0,0 +1,22 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	"context"
+
+	images "git.perx.ru/perxis/perxis-go/pkg/images"
+	endpoint "github.com/go-kit/kit/endpoint"
+)
+
+func Endpoints(svc images.Images) EndpointsSet {
+	return EndpointsSet{GetEndpoint: GetEndpoint(svc)}
+}
+
+func GetEndpoint(svc images.Images) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*GetRequest)
+		res0, res1 := svc.Get(arg0, req.Source, req.Opts)
+		return &GetResponse{Result: res0}, res1
+	}
+}