From 347cd06a4012931259224bc16ebe85249aa60fd0 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 1 Oct 2026 22:59:47 +0200 Subject: [PATCH] Feature/add MCP tool to get performance (part 2) (#8001) Add MCP tool to get performance --- .../src/app/endpoints/mcp/mcp.schemas.spec.ts | 16 ++++++++++ .../src/app/endpoints/mcp/mcp.service.spec.ts | 30 +++++++++++++++++++ apps/api/src/app/endpoints/mcp/mcp.service.ts | 5 ++-- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/apps/api/src/app/endpoints/mcp/mcp.schemas.spec.ts b/apps/api/src/app/endpoints/mcp/mcp.schemas.spec.ts index 2480b6726d..2039e7cd91 100644 --- a/apps/api/src/app/endpoints/mcp/mcp.schemas.spec.ts +++ b/apps/api/src/app/endpoints/mcp/mcp.schemas.spec.ts @@ -68,6 +68,22 @@ describe('GET_PERFORMANCE_PARAMETERS', () => { false ); }); + + it('Refuses an empty symbol of the holding', () => { + expect( + GET_PERFORMANCE_PARAMETERS.safeParse({ + holding: { dataSource: DataSource.YAHOO, symbol: '' } + }).success + ).toBe(false); + }); + + it('Refuses a symbol of the holding that contains only spaces', () => { + expect( + GET_PERFORMANCE_PARAMETERS.safeParse({ + holding: { dataSource: DataSource.YAHOO, symbol: ' ' } + }).success + ).toBe(false); + }); }); describe('IMPORT_ACTIVITIES_PARAMETERS', () => { diff --git a/apps/api/src/app/endpoints/mcp/mcp.service.spec.ts b/apps/api/src/app/endpoints/mcp/mcp.service.spec.ts index d4e37c695e..f4841896bd 100644 --- a/apps/api/src/app/endpoints/mcp/mcp.service.spec.ts +++ b/apps/api/src/app/endpoints/mcp/mcp.service.spec.ts @@ -260,6 +260,36 @@ describe('McpService', () => { }); }); + it('Resolves the mask of the data source of the Ghostfolio data provider', async () => { + configuration.DATA_SOURCES_GHOSTFOLIO_DATA_PROVIDER = [DataSource.YAHOO]; + configuration.ENABLE_FEATURE_SUBSCRIPTION = true; + + await mcpService.getPerformance({ + userId, + holding: { dataSource: DataSource.GHOSTFOLIO, symbol: 'AAPL' }, + range: 'max' + }); + + expect(apiService.buildFiltersFromQueryParams).toHaveBeenCalledWith( + expect.objectContaining({ filterByDataSource: DataSource.YAHOO }) + ); + }); + + it('Keeps the data source if the subscription is not enabled', async () => { + configuration.DATA_SOURCES_GHOSTFOLIO_DATA_PROVIDER = [DataSource.YAHOO]; + configuration.ENABLE_FEATURE_SUBSCRIPTION = false; + + await mcpService.getPerformance({ + userId, + holding: { dataSource: DataSource.GHOSTFOLIO, symbol: 'AAPL' }, + range: 'max' + }); + + expect(apiService.buildFiltersFromQueryParams).toHaveBeenCalledWith( + expect.objectContaining({ filterByDataSource: DataSource.GHOSTFOLIO }) + ); + }); + it('Gives the table of the performance of the filters in the range', async () => { expect( await mcpService.getPerformance({ userId, range: '2024' }) diff --git a/apps/api/src/app/endpoints/mcp/mcp.service.ts b/apps/api/src/app/endpoints/mcp/mcp.service.ts index d9d218267a..6a989dc856 100644 --- a/apps/api/src/app/endpoints/mcp/mcp.service.ts +++ b/apps/api/src/app/endpoints/mcp/mcp.service.ts @@ -104,10 +104,9 @@ export class McpService { userId }: z.infer & { userId: string }) { const filters = this.apiService.buildFiltersFromQueryParams({ + ...this.getHoldingFilterParameters({ holding }), filterByAccounts: accountIds, - filterByAssetClasses: assetClasses, - filterByDataSource: holding?.dataSource, - filterBySymbol: holding?.symbol + filterByAssetClasses: assetClasses }); const table = await this.portfolioTableService.getPerformanceTable({