Skip to content

Commit 67bacf9

Browse files
committed
fix: reduce hosted mcp runtime cost
1 parent ecac911 commit 67bacf9

4 files changed

Lines changed: 24 additions & 16 deletions

File tree

apps/web/app/api/mcp/route.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ import { createCorsHeaders, isOriginAllowed, mergeHeaders } from './route-helper
2626
const MAX_BATCH_SIZE = 10
2727
const MAX_REQUEST_SIZE = 100 * 1024 // 100KB
2828

29-
/** Set to "true" or "1" to disable DB and in-memory MCP telemetry (usage counts). */
30-
const MCP_TELEMETRY_DISABLED =
31-
process.env.MCP_TELEMETRY_DISABLED === 'true' || process.env.MCP_TELEMETRY_DISABLED === '1'
29+
/** Set to "true" or "1" to enable DB and in-memory MCP telemetry (usage counts). */
30+
const MCP_TELEMETRY_ENABLED =
31+
process.env.MCP_TELEMETRY_ENABLED === 'true' || process.env.MCP_TELEMETRY_ENABLED === '1'
3232

3333
interface McpRequest {
3434
jsonrpc: '2.0'
@@ -269,12 +269,12 @@ export async function POST(request: Request) {
269269
maxResponseChars: process.env.MCP_MAX_RESPONSE_CHARS
270270
? parseInt(process.env.MCP_MAX_RESPONSE_CHARS, 10)
271271
: undefined,
272-
telemetryEnabled: !MCP_TELEMETRY_DISABLED
272+
telemetryEnabled: MCP_TELEMETRY_ENABLED
273273
},
274274
body
275275
)
276276

277-
if (!MCP_TELEMETRY_DISABLED) {
277+
if (MCP_TELEMETRY_ENABLED) {
278278
const toolNames = extractToolNamesFromRequest(body)
279279
if (toolNames.length > 0) {
280280
prisma.mcpToolCall
@@ -382,7 +382,7 @@ export async function GET(request: Request) {
382382
maxResponseChars: process.env.MCP_MAX_RESPONSE_CHARS
383383
? parseInt(process.env.MCP_MAX_RESPONSE_CHARS, 10)
384384
: undefined,
385-
telemetryEnabled: !MCP_TELEMETRY_DISABLED
385+
telemetryEnabled: MCP_TELEMETRY_ENABLED
386386
}
387387
),
388388
rateLimitResult
@@ -405,7 +405,7 @@ export async function GET(request: Request) {
405405
}
406406
}
407407

408-
const usage = MCP_TELEMETRY_DISABLED ? {} : getTelemetryStats()
408+
const usage = MCP_TELEMETRY_ENABLED ? getTelemetryStats() : {}
409409
const tools = getToolDefinitions(getChecklists()).map((tool: { name: string }) => tool.name)
410410

411411
return Response.json(

apps/web/lib/rate-limit.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Ratelimit } from '@upstash/ratelimit'
22
import { Redis } from '@upstash/redis'
33

44
// Rate limiter configuration for MCP endpoint
5-
// Uses sliding window algorithm: 60 requests per minute per IP
5+
// Uses sliding window algorithm: 30 requests per minute per IP
66

77
let ratelimit: Ratelimit | null = null
88
let waitlistRatelimit: Ratelimit | null = null
@@ -36,8 +36,8 @@ function getRatelimiter(): Ratelimit | null {
3636

3737
ratelimit = new Ratelimit({
3838
redis,
39-
// Sliding window: 60 requests per 60 seconds
40-
limiter: Ratelimit.slidingWindow(60, '60 s'),
39+
// Sliding window: 30 requests per 60 seconds
40+
limiter: Ratelimit.slidingWindow(30, '60 s'),
4141
// Prefix for Redis keys
4242
prefix: 'mcp-ratelimit',
4343
// Analytics disabled by default (costs extra)
@@ -116,8 +116,8 @@ export async function checkRateLimit(identifier: string): Promise<RateLimitResul
116116
if (!limiter) {
117117
return {
118118
success: true,
119-
limit: 60,
120-
remaining: 60,
119+
limit: 30,
120+
remaining: 30,
121121
reset: Date.now() + 60000
122122
}
123123
}
@@ -135,8 +135,8 @@ export async function checkRateLimit(identifier: string): Promise<RateLimitResul
135135
console.error('[rate-limit] Rate limit check failed:', error)
136136
return {
137137
success: true,
138-
limit: 60,
139-
remaining: 60,
138+
limit: 30,
139+
remaining: 30,
140140
reset: Date.now() + 60000
141141
}
142142
}

apps/web/vercel.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
{
2+
"$schema": "https://openapi.vercel.sh/vercel.json",
3+
"git": {
4+
"deploymentEnabled": {
5+
"main": true,
6+
"**": false
7+
}
8+
},
29
"crons": [
310
{
411
"path": "/api/cron/supabase-keepalive",

docs/mcp-quality.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,10 @@ Tool responses are capped so the MCP doesn’t blow LLM token budgets:
210210
- **In-memory usage counters** in `packages/mcp`: every `tools/call` increments a per-tool counter when telemetry is enabled. Exposed via `getTelemetryStats()` and in **GET /api/mcp** as the optional `usage` object (e.g. `usage: { get_rule: 42, search_rules: 10 }`). Anonymous only; no IPs or identifiers. Counts reset on each deploy/restart.
211211
- **Database persistence**: Each `tools/call` is stored in the `McpToolCall` table (anonymous: `toolName`, `createdAt`). The API route writes after a successful request; DB errors are ignored so telemetry never breaks MCP responses. Apply migrations with `pnpm --filter @repo/auth db:migrate`.
212212

213-
**Disabling telemetry**
213+
**Enabling telemetry**
214214

215-
- Set **`MCP_TELEMETRY_DISABLED=true`** (or `MCP_TELEMETRY_DISABLED=1`) in the app environment. When set: in-memory counters are not updated and **GET /api/mcp** does not include `usage`; no rows are written to `McpToolCall`. The handler also accepts `createMcpHandler(getRules, getChecklists, { telemetryEnabled: false })` when creating it programmatically (e.g. in tests).
215+
- Telemetry is disabled by default for the public hosted endpoint to avoid database writes and analytics work for routine agent traffic.
216+
- Set **`MCP_TELEMETRY_ENABLED=true`** (or `MCP_TELEMETRY_ENABLED=1`) in the app environment to opt in. When enabled: in-memory counters are updated, **GET /api/mcp** includes `usage`, and successful `tools/call` requests write anonymous rows to `McpToolCall`. The handler also accepts `createMcpHandler(getRules, getChecklists, { telemetryEnabled: true })` when creating it programmatically (e.g. in tests).
216217

217218
**How to see it**
218219

0 commit comments

Comments
 (0)