MCP endpoints already had JwtAuthGuard applied but lacked per-route rate limiting and test coverage for security behavior. Add @Throttle decorators with appropriate limits (5 req/min for SSE connections, 30 req/min for server list and messages), unit tests verifying guard/throttle metadata, and E2E tests confirming 401 rejection for unauthenticated requests. Co-Authored-By: Paperclip <noreply@paperclip.ing>
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
import { test, expect, registerUser } from '../fixtures';
|
|
|
|
test.describe('MCP API — Auth Guards', () => {
|
|
test.describe('GET /mcp/servers', () => {
|
|
test('rejects unauthenticated request with 401', async ({ request }) => {
|
|
const res = await request.get('/mcp/servers');
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('returns server list for authenticated user', async ({ request }) => {
|
|
const { accessToken } = await registerUser(request);
|
|
|
|
const res = await request.get('/mcp/servers', {
|
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(200);
|
|
const body = await res.json();
|
|
expect(body).toHaveProperty('servers');
|
|
expect(Array.isArray(body.servers)).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
test.describe('GET /mcp/:serverName/sse', () => {
|
|
test('rejects unauthenticated SSE connection with 401', async ({ request }) => {
|
|
const res = await request.get('/mcp/search/sse');
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
});
|
|
|
|
test.describe('POST /mcp/:serverName/messages', () => {
|
|
test('rejects unauthenticated message with 401', async ({ request }) => {
|
|
const res = await request.post('/mcp/search/messages', {
|
|
params: { sessionId: 'fake-session' },
|
|
data: {},
|
|
});
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('returns 400 when sessionId is missing for authenticated user', async ({ request }) => {
|
|
const { accessToken } = await registerUser(request);
|
|
|
|
const res = await request.post('/mcp/search/messages', {
|
|
data: {},
|
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(400);
|
|
});
|
|
});
|
|
});
|