Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
18f1bd9
feat: initialise sse mcp server for razorpay
ChiragChiranjib May 3, 2025
2df3ffb
ref: add context_key construct for auth token
ChiragChiranjib May 3, 2025
cc83f23
feat: add auth token from env functionality
ChiragChiranjib May 3, 2025
f7c45c8
chore: correct git ignore file to include sse cmd
ChiragChiranjib May 3, 2025
d9aa67f
chore: add dockerfile for sse and update readme
ChiragChiranjib May 3, 2025
2ab3f83
fix: lint issues
ChiragChiranjib May 3, 2025
e080a84
fix: code formatting in pkg/mcpgo/server.go
ChiragChiranjib May 3, 2025
5a44134
chore: defer client auth reset
ChiragChiranjib May 3, 2025
ee872d7
chore: fix typos and update dockerfile
ChiragChiranjib May 3, 2025
e71e92e
chore: update docker file
ChiragChiranjib May 4, 2025
fc126e9
chore: add review suggested changes
ChiragChiranjib May 26, 2025
1567ae7
fix: add client from context
ChiragChiranjib May 26, 2025
4a02ca3
chore: add UTs for concurrent ctx checks
ChiragChiranjib May 26, 2025
23ef813
chore: consume auth header
ChiragChiranjib May 26, 2025
d730306
Merge branch 'main' of https://github.com/razorpay/razorpay-mcp-serve…
ChiragChiranjib May 26, 2025
95a26e8
chore: major upgrade razorpay-go
ChiragChiranjib May 26, 2025
cc4d938
Merge branch 'main' of https://github.com/razorpay/razorpay-mcp-serve…
ChiragChiranjib Jun 3, 2025
3131038
fix: add useragent support for sse & upgrade razorpay-go sdk
ChiragChiranjib Jun 3, 2025
dbc7181
fix: downgrade mcp library
ChiragChiranjib Jun 3, 2025
fbcb265
fix: resolve error with nil client
ChiragChiranjib Jun 3, 2025
d82d786
chore: add commit id to docker tags
ChiragChiranjib Jun 3, 2025
f6c1191
chore: add health check endpoints
ChiragChiranjib Jun 3, 2025
9007cdd
fix: lint issues
ChiragChiranjib Jun 3, 2025
b43823b
chore: add address as env for docker sse
ChiragChiranjib Jun 3, 2025
a5bcd41
fix: sse address
ChiragChiranjib Jun 3, 2025
7f1b055
chore: add mcp version
ChiragChiranjib Jun 3, 2025
429be29
feat: http mode rough draft
KarthikBoddeda Jun 3, 2025
48477fb
fix: port
KarthikBoddeda Jun 3, 2025
4f04a52
fix: UTs
KarthikBoddeda Jun 3, 2025
2d0b30c
fix: addrs
KarthikBoddeda Jun 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .cursor/rules/new-tool-from-docs.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Before the implementation use the documentation URL provided to figure out the r
Now follow the detailed implementation guide in [pkg/razorpay/README.md](mdc:../pkg/razorpay/README.md) for creating tools and start making code changes.

Other guidelines:
1. [Razorpay Go SDK Constants](mdc:https:/github.com/razorpay/razorpay-go/blob/master/constants/url.go) - Use these constants for specifying the api endpoints while writing the tests.
1. [Razorpay Go SDK Constants](mdc:https:/github.com/razorpay/razorpay-go/v2/blob/master/constants/url.go) - Use these constants for specifying the api endpoints while writing the tests.
2. Use the payload and response from the docs provided to write the positive test case for the tool.

STYLE:
Expand Down Expand Up @@ -251,9 +251,9 @@ Contains the Model Context Protocol implementation:
- `ToolParameter` types
- Response handling utilities (`NewToolResultJSON`, etc.)

### `github.com/razorpay/razorpay-go` - Razorpay Go SDK
### `github.com/razorpay/razorpay-go/v2` - Razorpay Go SDK

**Imported as:** `rzpsdk "github.com/razorpay/razorpay-go"`
**Imported as:** `rzpsdk "github.com/razorpay/razorpay-go/v2"`

Official Razorpay client library providing:
- `Client` struct with resource-specific clients (Payment, Order, PaymentLink, etc.)
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
IMAGE_TAG="${GITHUB_REF#refs/tags/}"
echo "tags=razorpay/mcp:${IMAGE_TAG},razorpay/mcp:latest" >> $GITHUB_OUTPUT
else
IMAGE_TAG="${GITHUB_SHA::7}" # short commit ID
IMAGE_TAG="${GITHUB_SHA}" # full commit SHA
echo "tags=razorpay/mcp:${IMAGE_TAG}" >> $GITHUB_OUTPUT
fi

Expand All @@ -45,3 +45,5 @@ jobs:
tags: ${{ steps.vars.outputs.tags }}
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
BUILD_DATE=${{ github.event.head_commit.timestamp }}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
/.go
/logs
/vendor
razorpay-mcp-server
/razorpay-mcp-server
25 changes: 22 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
FROM golang:1.24.2-alpine AS builder

# Install git
RUN apk add --no-cache git

WORKDIR /app

COPY go.mod go.sum ./
Expand All @@ -9,8 +12,10 @@
COPY . .

ARG VERSION="dev"
ARG COMMIT=""
ARG BUILD_DATE=""

RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-X main.version=${VERSION} -X main.commit=$(git rev-parse HEAD) -X main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" -o razorpay-mcp-server ./cmd/razorpay-mcp-server
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-X main.version=${VERSION} -X main.commit=${COMMIT:-$(git rev-parse HEAD 2>/dev/null || echo 'unknown')} -X main.date=${BUILD_DATE:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}" -o razorpay-mcp-server ./cmd/razorpay-mcp-server

FROM alpine:latest

Expand All @@ -26,12 +31,26 @@
# Change ownership of the application to the non-root user
RUN chown -R rzp:rzpgroup /app

ENV CONFIG="" \

Check warning on line 34 in Dockerfile

View workflow job for this annotation

GitHub Actions / build

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "RAZORPAY_KEY_SECRET") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 34 in Dockerfile

View workflow job for this annotation

GitHub Actions / build

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "RAZORPAY_KEY_ID") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
RAZORPAY_KEY_ID="" \
RAZORPAY_KEY_SECRET="" \
LOG_FILE=""
PORT="8090" \
MODE="stdio" \
LOG_FILE="" \
ADDRESS="mcp.razorpay.com"

# Switch to the non-root user
USER rzp

ENTRYPOINT ["sh", "-c", "./razorpay-mcp-server stdio --key ${RAZORPAY_KEY_ID} --secret ${RAZORPAY_KEY_SECRET} ${CONFIG:+--config ${CONFIG}} ${LOG_FILE:+--log-file ${LOG_FILE}}"]
# Expose the SSE server port (used in SSE mode)
EXPOSE ${PORT}

# Use shell form to allow variable substitution and conditional execution
ENTRYPOINT ["sh", "-c", "\
if [ \"$MODE\" = \"sse\" ]; then \
./razorpay-mcp-server sse --port ${PORT} --address ${ADDRESS} ${CONFIG:+--config ${CONFIG}}; \
elif [ \"$MODE\" = \"http\" ]; then \
./razorpay-mcp-server http --port ${PORT} ${CONFIG:+--config ${CONFIG}}; \
else \
./razorpay-mcp-server stdio --key ${RAZORPAY_KEY_ID} --secret ${RAZORPAY_KEY_SECRET} ${CONFIG:+--config ${CONFIG}} ${LOG_FILE:+--log-file ${LOG_FILE}}; \
fi"]
67 changes: 63 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,26 +186,85 @@ Once the build is ready, you need to specify the path to the binary executable i
}
```

## Usage with SSE Server

The Razorpay MCP Server also supports the Server-Sent Events (SSE) transport protocol, allowing you to run it as a standalone service that clients can connect to.

### Running the SSE Server with Docker

To run the server in SSE mode using the same Docker image:

```bash
# Run the SSE server on port 8090 (default)
docker run -p 8090:8090 \
-e MODE=sse \
-e PORT=8090 \
razorpay-mcp-server:latest
```

You can customize the port by setting the `PORT` environment variable.

### Testing with MCP Inspector

You can test your SSE server using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector) tool:

```bash
# Install MCP Inspector
npm install -g @modelcontextprotocol/inspector

# Open MCP Inspector tool
npx @modelcontextprotocol/inspector
```

This will open a browser interface where you can inspect and test the available tools on your SSE server.

## Configuration

The server requires the following configuration:

- `RAZORPAY_KEY_ID`: Your Razorpay API key ID
- `RAZORPAY_KEY_SECRET`: Your Razorpay API key secret
- `LOG_FILE` (optional): Path to log file for server logs
- `RAZORPAY_KEY_ID`: Your Razorpay API key ID (required for stdio mode)
- `RAZORPAY_KEY_SECRET`: Your Razorpay API key secret (required for stdio mode)
- `MODE`: Server mode ("stdio", "sse", or "http", default: "stdio")
- `PORT`: Port for SSE/HTTP server (default: "8090" for SSE, "8080" for HTTP)
- `ADDRESS`: Address to bind the server to (default: "localhost", used in SSE/HTTP mode)
- `LOG_FILE` (optional): Path to log file for stdio mode logs (SSE/HTTP modes always log to stdout)
- `TOOLSETS` (optional): Comma-separated list of toolsets to enable (default: "all")
- `READ_ONLY` (optional): Run server in read-only mode (default: false)

### Command Line Flags

The server supports the following command line flags:
The server supports different commands and flags:

#### stdio mode:
```bash
./razorpay-mcp-server stdio [flags]
```
- `--key` or `-k`: Your Razorpay API key ID
- `--secret` or `-s`: Your Razorpay API key secret
- `--log-file` or `-l`: Path to log file
- `--toolsets` or `-t`: Comma-separated list of toolsets to enable
- `--read-only`: Run server in read-only mode

#### SSE mode:
```bash
./razorpay-mcp-server sse [flags]
```
- `--address` or `-a`: Address to bind the server to (default: "localhost")
- `--port` or `-p`: Port to run the SSE server on (default: 8080)
- `--toolsets` or `-t`: Comma-separated list of toolsets to enable
- `--read-only`: Run server in read-only mode

#### HTTP mode:
```bash
./razorpay-mcp-server http [flags]
```
- `--address` or `-a`: Address to bind the server to (default: "localhost")
- `--port` or `-p`: Port to run the HTTP server on (default: 8080)
- `--toolsets` or `-t`: Comma-separated list of toolsets to enable
- `--read-only`: Run server in read-only mode

Note: SSE and HTTP modes log to stdout for better container integration. Authentication is handled via Bearer tokens in HTTP mode and SSE context in SSE mode.

## Debugging the Server

You can use the standard Go debugging tools to troubleshoot issues with the server. Log files can be specified using the `--log-file` flag (defaults to ./logs)
Expand Down
99 changes: 99 additions & 0 deletions cmd/razorpay-mcp-server/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package main

import (
"context"
"fmt"
"log/slog"
"os"
"os/signal"
"syscall"

"github.com/spf13/cobra"
"github.com/spf13/viper"

rzpsdk "github.com/razorpay/razorpay-go/v2"

"github.com/razorpay/razorpay-mcp-server/pkg/razorpay"
)

// httpCmd starts the mcp server in http transport mode
var httpCmd = &cobra.Command{
Use: "http",
Short: "start the http server for direct JSON-RPC calls",
Run: func(cmd *cobra.Command, args []string) {
// Create stdout logger
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelError,
}))

// Get toolsets to enable from config
enabledToolsets := viper.GetStringSlice("toolsets")

// Get read-only mode from config
readOnly := viper.GetBool("read_only")

err := runHTTPServer(logger, nil, enabledToolsets, readOnly)
if err != nil {
logger.Error("error running http server", "error", err)
os.Exit(1)
}
},
}

func runHTTPServer(
log *slog.Logger,
client *rzpsdk.Client,
enabledToolsets []string,
readOnly bool,
) error {
ctx, stop := signal.NotifyContext(
context.Background(),
os.Interrupt,
syscall.SIGTERM,
)
defer stop()

srv, err := razorpay.NewServer(
log,
client,
"1.0.0",
enabledToolsets,
readOnly,
)
if err != nil {
return fmt.Errorf("failed to create server: %w", err)
}
srv.RegisterTools()

httpSrv, err := razorpay.NewHTTPServer(
srv,
razorpay.NewHTTPConfig(
razorpay.WithHTTPAddress("localhost"),
razorpay.WithHTTPPort(viper.GetInt("port")),
),
)
if err != nil {
return fmt.Errorf("failed to create http server: %w", err)
}

errC := make(chan error, 1)
go func() {
log.Info("starting http server")
errC <- httpSrv.Start()
}()

log.Info("Razorpay MCP Server running on http\n")

// Wait for shutdown signal
select {
case <-ctx.Done():
log.Info("shutting down server...")
return httpSrv.Shutdown(ctx)
case err := <-errC:
if err != nil {
log.Error("server error", "error", err)
return err
}
return nil
}
}
6 changes: 6 additions & 0 deletions cmd/razorpay-mcp-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,17 @@ func init() {
rootCmd.PersistentFlags().StringP("log-file", "l", "", "path to the log file")
rootCmd.PersistentFlags().StringSliceP("toolsets", "t", []string{}, "comma-separated list of toolsets to enable")
rootCmd.PersistentFlags().Bool("read-only", false, "run server in read-only mode")
rootCmd.PersistentFlags().StringP("address", "a", "localhost", "address to bind the sse server to")
rootCmd.PersistentFlags().IntP("port", "p", 8080, "port to bind the sse server to")

// bind flags to viper
_ = viper.BindPFlag("key", rootCmd.PersistentFlags().Lookup("key"))
_ = viper.BindPFlag("secret", rootCmd.PersistentFlags().Lookup("secret"))
_ = viper.BindPFlag("log_file", rootCmd.PersistentFlags().Lookup("log-file"))
_ = viper.BindPFlag("toolsets", rootCmd.PersistentFlags().Lookup("toolsets"))
_ = viper.BindPFlag("read_only", rootCmd.PersistentFlags().Lookup("read-only"))
_ = viper.BindPFlag("address", rootCmd.PersistentFlags().Lookup("address"))
_ = viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port"))

// Set environment variable mappings
_ = viper.BindEnv("key", "RAZORPAY_KEY_ID") // Maps RAZORPAY_KEY_ID to key
Expand All @@ -57,6 +61,8 @@ func init() {

// subcommands
rootCmd.AddCommand(stdioCmd)
rootCmd.AddCommand(sseCmd)
rootCmd.AddCommand(httpCmd)
}

// initConfig reads in config file and ENV variables if set.
Expand Down
Loading