index.test.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { createMocks } from 'node-mocks-http'
  2. import { beforeEach, describe, expect, it, vi } from 'vitest'
  3. import handler from '../../../../pages/api/mcp/index'
  4. import { mswServer } from '@/tests/lib/msw'
  5. // Mock the MCP SDK and Briven MCP server to avoid Hono/node-mocks-http compatibility issues.
  6. //
  7. // Starting with MCP SDK v1.25.x (required by @supabase/mcp-server-supabase@0.6.2), the SDK
  8. // uses @hono/node-server for converting between Node.js HTTP and Web Standard APIs. This is
  9. // incompatible with the node-mocks-http library used in these tests.
  10. //
  11. // Since these tests focus on query parameter validation in the API handler rather than
  12. // testing the MCP transport implementation, we mock both packages to avoid hitting the
  13. // incompatible Hono code paths.
  14. vi.mock('@modelcontextprotocol/sdk/server/streamableHttp.js', () => ({
  15. StreamableHTTPServerTransport: vi.fn().mockImplementation(function () {
  16. return { handleRequest: vi.fn().mockResolvedValue(undefined) }
  17. }),
  18. }))
  19. vi.mock('@supabase/mcp-server-supabase', () => ({
  20. createBrivenMcpServer: vi.fn().mockReturnValue({
  21. connect: vi.fn().mockResolvedValue(undefined),
  22. }),
  23. }))
  24. describe('/api/mcp', () => {
  25. beforeEach(() => {
  26. // Disable MSW for these tests
  27. mswServer.close()
  28. // Clear mock state between tests
  29. vi.clearAllMocks()
  30. })
  31. describe('Method handling', async () => {
  32. it('should handle POST requests', async () => {
  33. const { req, res } = createMocks({
  34. method: 'POST',
  35. query: {},
  36. body: {},
  37. })
  38. await handler(req, res)
  39. expect(res._getStatusCode()).not.toBe(405)
  40. })
  41. it('should return 405 for non-POST methods', async () => {
  42. const { req, res } = createMocks({
  43. method: 'GET',
  44. })
  45. await handler(req, res)
  46. expect(res._getStatusCode()).toBe(405)
  47. expect(JSON.parse(res._getData())).toEqual({
  48. error: { message: 'Method GET Not Allowed' },
  49. })
  50. expect(res._getHeaders()).toEqual({ allow: ['POST'], 'content-type': 'application/json' })
  51. })
  52. })
  53. describe('Query validation', async () => {
  54. it('should accept valid feature groups', async () => {
  55. const { req, res } = createMocks({
  56. method: 'POST',
  57. query: { features: 'docs,database' },
  58. body: {},
  59. })
  60. await handler(req, res)
  61. expect(res._getStatusCode()).not.toBe(400)
  62. })
  63. it('should reject invalid feature groups', async () => {
  64. const { req, res } = createMocks({
  65. method: 'POST',
  66. query: { features: 'invalid,unknown' },
  67. body: {},
  68. })
  69. await handler(req, res)
  70. expect(res._getStatusCode()).toBe(400)
  71. expect(JSON.parse(res._getData())).toHaveProperty('error')
  72. })
  73. it('should work without features parameter', async () => {
  74. const { req, res } = createMocks({
  75. method: 'POST',
  76. query: {},
  77. body: {},
  78. })
  79. await handler(req, res)
  80. expect(res._getStatusCode()).not.toBe(400)
  81. })
  82. })
  83. })