Skip to main content
Glama

New Relic MCP Server

by cloudbring
apm.steps.ts9.76 kB
import { Given, Then, When } from '@amiceli/vitest-cucumber'; import { expect, vi } from 'vitest'; import { context, resetContext } from './shared.steps'; let targetAccountId: string = ''; Given('I have access to APM applications in my account', () => { if (!context.mockClient) return; context.mockClient.listApmApplications = vi.fn().mockResolvedValue([ { guid: 'app-guid-1', name: 'My App 1', language: 'nodejs', reporting: true, alertSeverity: 'NOT_ALERTING', tags: { env: 'production' }, }, { guid: 'app-guid-2', name: 'My App 2', language: 'java', reporting: true, alertSeverity: 'WARNING', tags: { env: 'staging' }, }, ]); }); Given('I want to list APM applications from a specific account', () => { targetAccountId = '789012'; }); Given('there are no APM applications in the account', () => { if (!context.mockClient) return; context.mockClient.listApmApplications = vi.fn().mockResolvedValue([]); }); Given('I provide an invalid account ID', () => { targetAccountId = 'invalid-id'; }); Given('the New Relic API returns an error for the APM applications query', () => { if (!context.mockClient) return; context.mockClient.listApmApplications = vi .fn() .mockRejectedValue(new Error('API Error: Rate limit exceeded')); }); Given('I have access to APM applications in multiple accounts', () => { // This is handled by the mock setup }); Given('there are more than 250 APM applications in the account', () => { if (!context.mockClient) return; const apps = Array.from({ length: 300 }, (_, i) => ({ guid: `app-guid-${i}`, name: `App ${i}`, language: 'nodejs', reporting: true, alertSeverity: 'NOT_ALERTING', tags: {}, })); context.mockClient.listApmApplications = vi.fn().mockResolvedValue(apps); }); When('I call the {string} tool with a target account ID', async (toolName: string) => { resetContext(); context.toolName = toolName; if (!context.server) { const { NewRelicMCPServer } = await import('../../src/server'); context.mockClient = { validateCredentials: vi.fn().mockResolvedValue(true), getAccountDetails: vi.fn().mockResolvedValue({ accountId: '123456', name: 'Test Account' }), listApmApplications: vi.fn().mockResolvedValue([]), executeNerdGraphQuery: vi.fn().mockResolvedValue({ data: {} }), } as any; context.server = new NewRelicMCPServer(context.mockClient); } try { context.lastResponse = await context.server.executeTool(toolName, { target_account_id: targetAccountId || context.accountId, }); context.lastError = null; } catch (error: any) { context.lastError = error; context.lastResponse = null; } }); When('I receive the list of applications', () => { // This is handled by the previous When step }); Then('the response should contain a list of APM applications', () => { expect(context.lastResponse).toBeDefined(); expect(Array.isArray(context.lastResponse)).toBe(true); }); Then('each application should have a GUID', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(app.guid).toBeDefined(); expect(typeof app.guid).toBe('string'); }); } }); Then('each application should have a name', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(app.name).toBeDefined(); expect(typeof app.name).toBe('string'); }); } }); Then('each application should have a language', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(app.language).toBeDefined(); expect(typeof app.language).toBe('string'); }); } }); Then('the response should contain applications from the specified account', () => { expect(context.mockClient?.listApmApplications).toHaveBeenCalledWith(targetAccountId); }); Then('all returned applications should belong to the correct account', () => { // This is validated by the mock being called with the correct account ID expect(context.mockClient?.listApmApplications).toHaveBeenCalled(); }); Then('the search should be limited to the specified account', () => { expect(context.mockClient?.listApmApplications).toHaveBeenCalledWith( expect.stringMatching(/\d+/) ); }); Then('the response should contain an empty list', () => { expect(context.lastResponse).toBeDefined(); expect(Array.isArray(context.lastResponse)).toBe(true); expect(context.lastResponse).toHaveLength(0); }); Then('the response should indicate zero total count', () => { expect(context.lastResponse).toHaveLength(0); }); Then('the error should indicate that the account was not found', () => { expect(context.lastError?.message).toMatch(/account.*not found|invalid/i); }); Then('the response should contain the API error', () => { expect(context.lastError).toBeDefined(); expect(context.lastError?.message).toContain('API Error'); }); Then('the error should be properly formatted', () => { expect(context.lastError?.message).toBeDefined(); expect(typeof context.lastError?.message).toBe('string'); }); Then('each application should include reporting status', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(app).toHaveProperty('reporting'); expect(typeof app.reporting).toBe('boolean'); }); } }); Then('each application should include alert severity', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(app).toHaveProperty('alertSeverity'); }); } }); Then('each application should include tags information', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(app).toHaveProperty('tags'); expect(typeof app.tags).toBe('object'); }); } }); Then('each application should include language information', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(app).toHaveProperty('language'); expect(typeof app.language).toBe('string'); }); } }); Then('the response should contain applications from the default account', () => { expect(context.mockClient?.listApmApplications).toHaveBeenCalledWith(expect.any(String)); }); Then('the search should be limited to the configured account', () => { expect(context.mockClient?.listApmApplications).toHaveBeenCalledWith( context.accountId || expect.any(String) ); }); Then('the response should include pagination information', () => { // For large result sets, pagination should be handled expect(context.lastResponse).toBeDefined(); }); Then('the response should include a nextCursor if applicable', () => { // Pagination cursor handling if ( context.lastResponse && Array.isArray(context.lastResponse) && context.lastResponse.length >= 250 ) { // In a real implementation, this would check for pagination metadata expect(true).toBe(true); } }); Then('the response should include a total count', () => { expect(context.lastResponse).toBeDefined(); expect(Array.isArray(context.lastResponse)).toBe(true); }); Then('the response should only include APM domain applications', () => { // This is ensured by the listApmApplications method filtering expect(true).toBe(true); }); Then('the response should only include APPLICATION type entities', () => { // This is ensured by the listApmApplications method filtering expect(true).toBe(true); }); Then('the search should be properly filtered', () => { expect(context.mockClient?.listApmApplications).toHaveBeenCalled(); }); Then('the language should be a valid programming language', () => { if (Array.isArray(context.lastResponse)) { const validLanguages = ['nodejs', 'java', 'python', 'ruby', 'go', 'dotnet', 'php', 'unknown']; context.lastResponse.forEach((app: any) => { expect(validLanguages).toContain(app.language.toLowerCase()); }); } }); Then("the language should reflect the application's technology stack", () => { // This is validated by the language field being present expect(true).toBe(true); }); Then('the reporting status should indicate whether the application is currently reporting', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(typeof app.reporting).toBe('boolean'); }); } }); Then('the reporting status should be accurate', () => { // This is mocked data, so we trust it's accurate expect(true).toBe(true); }); Then('the alert severity should reflect the current alert state', () => { if (Array.isArray(context.lastResponse)) { const validSeverities = ['NOT_ALERTING', 'WARNING', 'CRITICAL', 'NOT_CONFIGURED']; context.lastResponse.forEach((app: any) => { if (app.alertSeverity) { expect(validSeverities).toContain(app.alertSeverity); } }); } }); Then('the alert severity should be properly categorized', () => { // Validated in the previous step expect(true).toBe(true); }); Then('the tags should be properly structured as key-value pairs', () => { if (Array.isArray(context.lastResponse)) { context.lastResponse.forEach((app: any) => { expect(typeof app.tags).toBe('object'); Object.entries(app.tags).forEach(([key, value]) => { expect(typeof key).toBe('string'); expect(typeof value).toBe('string'); }); }); } }); Then('the tags should provide useful categorization information', () => { // Tags are present and structured correctly expect(true).toBe(true); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cloudbring/newrelic-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server