Skip to content

Commit 88769b3

Browse files
committed
design: add design for rate limiting
I added an example for how rate limiting should be implemented using middleware.
1 parent abb650e commit 88769b3

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

design/design.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,35 @@ server.AddReceivingMiddleware(withLogging)
470470
471471
**Differences from mcp-go**: Version 0.26.0 of mcp-go defines 24 server hooks. Each hook consists of a field in the `Hooks` struct, a `Hooks.Add` method, and a type for the hook function. These are rarely used. The most common is `OnError`, which occurs fewer than ten times in open-source code.
472472
473+
#### Rate Limiting
474+
475+
Rate limiting can be configured using middleware.
476+
477+
As an example, this code adds a per-session rate limiter using the [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) package.
478+
479+
```go
480+
// PerSessionRateLimiterMiddleware creates a middleware that applies rate limiting
481+
// on a per-session basis for receiving requests.
482+
func PerSessionRateLimiterMiddleware[S Session](limit rate.Limit, burst int) Middleware[S] {
483+
var sessionLimiters sync.Map // map[*jsonrpc2.Connection]*rate.Limiter
484+
485+
return func(h MethodHandler[S]) MethodHandler[S] {
486+
return func(ctx context.Context, session S, method string, params Params) (Result, error) {
487+
conn := session.getConn()
488+
489+
limiter, _ := sessionLimiters.LoadOrStore(conn, rate.NewLimiter(limit, burst))
490+
rateLimiter := limiter.(*rate.Limiter)
491+
492+
if !rateLimiter.Allow() {
493+
return nil, jsonrpc2.ErrServerOverloaded
494+
}
495+
return h(ctx, session, method, params)
496+
}
497+
}
498+
}
499+
server.AddReceivingMiddleware(PerSessionRateLimiterMiddleware[*ServerSession](rate.Every(time.Second * 2), Burst: 5))
500+
```
501+
473502
### Errors
474503
475504
With the exception of tool handler errors, protocol errors are handled transparently as Go errors: errors in server-side feature handlers are propagated as errors from calls from the `ClientSession`, and vice-versa.

0 commit comments

Comments
 (0)