Repository: payloadcms/payload
File: test/plugin-mcp/int.spec.ts (TypeScript)

Code before:
    it('should create an API Key', async () => {
      const doc = await payload.create({
        collection: 'payload-mcp-api-keys',
        data: {
          apiKey: randomUUID(),
          enableAPIKey: true,
          label: 'Test API Key',
          posts: { create: true, find: true },
          products: { find: true },
          user: userId,
        },
      })

      expect(doc).toBeDefined()
      expect(doc.user).toBeDefined()
      // @ts-expect-error - doc.user is a string | User
      expect(doc.user?.id).toBe(userId)
      expect(doc.label).toBe('Test API Key')
      expect(doc.posts?.find).toBe(true)
      expect(doc.posts?.create).toBe(true)
      expect(doc['payload-mcp-tool']?.['diceRoll']).toBe(true)
      expect(doc['payload-mcp-resource']?.['data']).toBe(true)
      expect(doc['payload-mcp-resource']?.['dataByID']).toBe(true)
      expect(doc['payload-mcp-prompt']?.['echo']).toBe(true)
      expect(doc.products?.find).toBe(true)
      expect(doc.products?.create).toBe(false)
      expect(doc.products?.update).toBe(false)
      expect(doc.products?.delete).toBe(false)
      expect(doc.media?.find).toBe(false)
      expect(doc.media?.update).toBe(false)
      expect(typeof doc.apiKey).toBe('string')
      expect(doc.apiKey).toHaveLength(36)
      expect(doc.override).toBe('This field added by overrideApiKeyCollection')
    })

    it('should not allow GET /api/mcp', async () => {
      const apiKey = await getApiKey()
      const data = await restClient
        .GET(`/mcp`, {
          headers: {
            Authorization: `Bearer ${apiKey}`,
          },
        })
        .then((res) => res.json())

      expect(data).toBeDefined()
      // @ts-expect-error - data is a valid property
      expect(data.jsonrpc).toBe('2.0')
      // @ts-expect-error - data is a valid property
      expect(data.error).toBeDefined()
      // @ts-expect-error - data is a valid property

Review comment (suggestion):
This `waitFor` may need to be in the other test for multiple requests, but from what I was experiencing locally it was not required.

Code after:
  describe('Create MCP Handler', () => {
    it('should invoke onEvent callback when MCP requests are processed', async () => {
      capturedMcpEvents.length = 0

      const apiKey = await getApiKey()
      const response = await restClient.POST('/mcp', {
        body: JSON.stringify({
          id: 1,
          jsonrpc: '2.0',
          method: 'tools/list',
          params: {},
        }),
        headers: {
          Accept: 'application/json, text/event-stream',
          Authorization: `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
        },
      })

      const json = await parseStreamResponse(response)

      expect(json).toBeDefined()
      expect(json.result).toBeDefined()

      // Events are emitted asynchronously after the response stream completes
      await vi.waitFor(() => expect(capturedMcpEvents.length).toBeGreaterThan(0), {
        timeout: 2000,
        interval: 100,
      })
    })

    it('should capture events for multiple sequential requests', async () => {
      capturedMcpEvents.length = 0

      const apiKey = await getApiKey()

      // First request
      await restClient.POST('/mcp', {
        body: JSON.stringify({
          id: 1,
          jsonrpc: '2.0',
          method: 'ping',
          params: {},
        }),
        headers: {
          Accept: 'application/json, text/event-stream',
          Authorization: `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
        },
      })