@dxheroes/local-mcp-backend 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
 
2
- > @dxheroes/local-mcp-backend@0.12.0 build /home/runner/work/local-mcp-gateway/local-mcp-gateway/apps/backend
2
+ > @dxheroes/local-mcp-backend@0.13.0 build /home/runner/work/local-mcp-gateway/local-mcp-gateway/apps/backend
3
3
  > nest build
4
4
 
5
5
  -  TSC  Initializing type checker...
6
6
  ✔  TSC  Initializing type checker...
7
7
  >  TSC  Found 0 issues.
8
8
  >  SWC  Running...
9
- Successfully compiled: 68 files with swc (106.21ms)
9
+ Successfully compiled: 70 files with swc (113.12ms)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.13.0](https://github.com/DXHeroes/local-mcp-gateway/compare/backend-v0.12.0...backend-v0.13.0) (2026-03-16)
4
+
5
+
6
+ ### Features
7
+
8
+ * **mcp:** implement server-level tool configuration management ([f8a1f58](https://github.com/DXHeroes/local-mcp-gateway/commit/f8a1f58d28c4da9a8a05034b1665ba2f58338d01))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @dxheroes/local-mcp-core bumped to 0.10.0
16
+ * @dxheroes/local-mcp-database bumped to 0.7.0
17
+ * @dxheroes/mcp-abra-flexi bumped to 0.4.1
18
+ * @dxheroes/mcp-fakturoid bumped to 0.4.1
19
+ * @dxheroes/mcp-gemini-deep-research bumped to 0.5.9
20
+ * @dxheroes/mcp-merk bumped to 0.3.9
21
+ * @dxheroes/mcp-toggl bumped to 0.3.9
22
+ * devDependencies
23
+ * @dxheroes/local-mcp-config bumped to 0.4.14
24
+
3
25
  ## [0.12.0](https://github.com/DXHeroes/local-mcp-gateway/compare/backend-v0.11.0...backend-v0.12.0) (2026-03-16)
4
26
 
5
27
 
@@ -0,0 +1,286 @@
1
+ /**
2
+ * Tests for McpService — server-level tool configurations (allowlist)
3
+ */ import { ForbiddenException } from "@nestjs/common";
4
+ import { beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { McpService } from "../../modules/mcp/mcp.service.js";
6
+ import { McpRegistry } from "../../modules/mcp/mcp-registry.js";
7
+ // Mock @dxheroes/local-mcp-core
8
+ const mockInitialize = vi.fn().mockResolvedValue(undefined);
9
+ const mockListTools = vi.fn().mockResolvedValue([
10
+ {
11
+ name: 'read_file',
12
+ description: 'Read a file'
13
+ },
14
+ {
15
+ name: 'write_file',
16
+ description: 'Write a file'
17
+ },
18
+ {
19
+ name: 'delete_file',
20
+ description: 'Delete a file'
21
+ }
22
+ ]);
23
+ const mockShutdown = vi.fn().mockResolvedValue(undefined);
24
+ vi.mock('@dxheroes/local-mcp-core', async (importOriginal)=>{
25
+ const actual = await importOriginal();
26
+ return {
27
+ ...actual,
28
+ ExternalMcpServer: class MockExternalMcpServer {
29
+ constructor(config){
30
+ this.initialize = mockInitialize;
31
+ this.listTools = mockListTools;
32
+ this.shutdown = mockShutdown;
33
+ this.config = config;
34
+ }
35
+ },
36
+ RemoteHttpMcpServer: class MockRemoteHttpMcpServer {
37
+ constructor(config){
38
+ this.initialize = mockInitialize;
39
+ this.listTools = mockListTools;
40
+ this.config = config;
41
+ }
42
+ },
43
+ RemoteSseMcpServer: class MockRemoteSseMcpServer {
44
+ constructor(config){
45
+ this.initialize = mockInitialize;
46
+ this.listTools = mockListTools;
47
+ this.config = config;
48
+ }
49
+ }
50
+ };
51
+ });
52
+ describe('McpService — Tool Configs', ()=>{
53
+ let service;
54
+ // biome-ignore lint: test mock
55
+ let prisma;
56
+ let registry;
57
+ let debugService;
58
+ let sharingService;
59
+ const server = {
60
+ id: 'srv-1',
61
+ name: 'Test Server',
62
+ type: 'remote_http',
63
+ config: '{"url":"https://example.com/mcp"}',
64
+ apiKeyConfig: null,
65
+ oauthConfig: null,
66
+ userId: 'user-a',
67
+ profiles: [],
68
+ oauthToken: null,
69
+ toolsCache: []
70
+ };
71
+ beforeEach(()=>{
72
+ prisma = {
73
+ mcpServer: {
74
+ findMany: vi.fn().mockResolvedValue([]),
75
+ findUnique: vi.fn().mockResolvedValue(null),
76
+ create: vi.fn().mockResolvedValue({
77
+ id: 'new-1'
78
+ }),
79
+ update: vi.fn().mockResolvedValue({}),
80
+ delete: vi.fn().mockResolvedValue(undefined)
81
+ },
82
+ member: {
83
+ findMany: vi.fn().mockResolvedValue([])
84
+ },
85
+ mcpServerToolsCache: {
86
+ findMany: vi.fn().mockResolvedValue([])
87
+ },
88
+ mcpServerToolConfig: {
89
+ findMany: vi.fn().mockResolvedValue([]),
90
+ deleteMany: vi.fn().mockResolvedValue({
91
+ count: 0
92
+ }),
93
+ createMany: vi.fn().mockResolvedValue({
94
+ count: 0
95
+ })
96
+ },
97
+ $transaction: vi.fn(async (fn)=>{
98
+ return fn(prisma);
99
+ })
100
+ };
101
+ registry = new McpRegistry();
102
+ debugService = {
103
+ createLog: vi.fn().mockResolvedValue({
104
+ id: 'log-1'
105
+ }),
106
+ updateLog: vi.fn().mockResolvedValue({})
107
+ };
108
+ sharingService = {
109
+ getSharedResourceIds: vi.fn().mockResolvedValue([]),
110
+ isSharedWith: vi.fn().mockResolvedValue(false),
111
+ getPermission: vi.fn().mockResolvedValue(null)
112
+ };
113
+ service = new McpService(prisma, registry, debugService, sharingService);
114
+ });
115
+ describe('getServerToolConfigs', ()=>{
116
+ it('returns all tools as enabled when no configs exist (unconfigured server)', async ()=>{
117
+ prisma.mcpServer.findUnique.mockResolvedValue(server);
118
+ prisma.mcpServerToolConfig.findMany.mockResolvedValue([]);
119
+ const result = await service.getServerToolConfigs('srv-1', 'user-a');
120
+ expect(result.hasConfigs).toBe(false);
121
+ expect(result.tools).toHaveLength(3);
122
+ expect(result.tools.every((t)=>t.isEnabled)).toBe(true);
123
+ });
124
+ it('returns tools with config records using their isEnabled value', async ()=>{
125
+ prisma.mcpServer.findUnique.mockResolvedValue(server);
126
+ prisma.mcpServerToolConfig.findMany.mockResolvedValue([
127
+ {
128
+ id: 'tc-1',
129
+ mcpServerId: 'srv-1',
130
+ toolName: 'read_file',
131
+ isEnabled: true
132
+ },
133
+ {
134
+ id: 'tc-2',
135
+ mcpServerId: 'srv-1',
136
+ toolName: 'write_file',
137
+ isEnabled: false
138
+ },
139
+ {
140
+ id: 'tc-3',
141
+ mcpServerId: 'srv-1',
142
+ toolName: 'delete_file',
143
+ isEnabled: false
144
+ }
145
+ ]);
146
+ const result = await service.getServerToolConfigs('srv-1', 'user-a');
147
+ expect(result.hasConfigs).toBe(true);
148
+ expect(result.tools).toHaveLength(3);
149
+ const readFile = result.tools.find((t)=>t.name === 'read_file');
150
+ const writeFile = result.tools.find((t)=>t.name === 'write_file');
151
+ const deleteFile = result.tools.find((t)=>t.name === 'delete_file');
152
+ expect(readFile?.isEnabled).toBe(true);
153
+ expect(writeFile?.isEnabled).toBe(false);
154
+ expect(deleteFile?.isEnabled).toBe(false);
155
+ });
156
+ it('treats new tools (no config record) as disabled when configs exist', async ()=>{
157
+ prisma.mcpServer.findUnique.mockResolvedValue(server);
158
+ // Only read_file has a config — write_file and delete_file are "new"
159
+ prisma.mcpServerToolConfig.findMany.mockResolvedValue([
160
+ {
161
+ id: 'tc-1',
162
+ mcpServerId: 'srv-1',
163
+ toolName: 'read_file',
164
+ isEnabled: true
165
+ }
166
+ ]);
167
+ const result = await service.getServerToolConfigs('srv-1', 'user-a');
168
+ expect(result.hasConfigs).toBe(true);
169
+ const readFile = result.tools.find((t)=>t.name === 'read_file');
170
+ const writeFile = result.tools.find((t)=>t.name === 'write_file');
171
+ const deleteFile = result.tools.find((t)=>t.name === 'delete_file');
172
+ expect(readFile?.isEnabled).toBe(true);
173
+ expect(readFile?.hasConfig).toBe(true);
174
+ expect(writeFile?.isEnabled).toBe(false);
175
+ expect(writeFile?.hasConfig).toBe(false);
176
+ expect(deleteFile?.isEnabled).toBe(false);
177
+ expect(deleteFile?.hasConfig).toBe(false);
178
+ });
179
+ it('throws ForbiddenException for non-owner without sharing', async ()=>{
180
+ prisma.mcpServer.findUnique.mockResolvedValue(server);
181
+ await expect(service.getServerToolConfigs('srv-1', 'user-b')).rejects.toThrow(ForbiddenException);
182
+ });
183
+ it('allows non-owner with sharing to view configs', async ()=>{
184
+ prisma.mcpServer.findUnique.mockResolvedValue(server);
185
+ sharingService.isSharedWith.mockResolvedValue(true);
186
+ prisma.mcpServerToolConfig.findMany.mockResolvedValue([]);
187
+ const result = await service.getServerToolConfigs('srv-1', 'user-b');
188
+ expect(result.tools).toHaveLength(3);
189
+ });
190
+ });
191
+ describe('updateServerToolConfigs', ()=>{
192
+ it('creates config records for all tools in a transaction', async ()=>{
193
+ prisma.mcpServer.findUnique.mockResolvedValue(server);
194
+ prisma.mcpServerToolConfig.findMany.mockResolvedValue([
195
+ {
196
+ id: 'tc-1',
197
+ mcpServerId: 'srv-1',
198
+ toolName: 'read_file',
199
+ isEnabled: true
200
+ },
201
+ {
202
+ id: 'tc-2',
203
+ mcpServerId: 'srv-1',
204
+ toolName: 'write_file',
205
+ isEnabled: false
206
+ },
207
+ {
208
+ id: 'tc-3',
209
+ mcpServerId: 'srv-1',
210
+ toolName: 'delete_file',
211
+ isEnabled: false
212
+ }
213
+ ]);
214
+ await service.updateServerToolConfigs('srv-1', [
215
+ {
216
+ toolName: 'read_file',
217
+ isEnabled: true
218
+ },
219
+ {
220
+ toolName: 'write_file',
221
+ isEnabled: false
222
+ },
223
+ {
224
+ toolName: 'delete_file',
225
+ isEnabled: false
226
+ }
227
+ ], 'user-a');
228
+ expect(prisma.$transaction).toHaveBeenCalled();
229
+ expect(prisma.mcpServerToolConfig.deleteMany).toHaveBeenCalledWith({
230
+ where: {
231
+ mcpServerId: 'srv-1'
232
+ }
233
+ });
234
+ expect(prisma.mcpServerToolConfig.createMany).toHaveBeenCalledWith({
235
+ data: [
236
+ {
237
+ mcpServerId: 'srv-1',
238
+ toolName: 'read_file',
239
+ isEnabled: true
240
+ },
241
+ {
242
+ mcpServerId: 'srv-1',
243
+ toolName: 'write_file',
244
+ isEnabled: false
245
+ },
246
+ {
247
+ mcpServerId: 'srv-1',
248
+ toolName: 'delete_file',
249
+ isEnabled: false
250
+ }
251
+ ]
252
+ });
253
+ });
254
+ it('throws ForbiddenException for non-owner', async ()=>{
255
+ prisma.mcpServer.findUnique.mockResolvedValue(server);
256
+ await expect(service.updateServerToolConfigs('srv-1', [
257
+ {
258
+ toolName: 'read_file',
259
+ isEnabled: true
260
+ }
261
+ ], 'user-b')).rejects.toThrow(ForbiddenException);
262
+ });
263
+ it('allows admin shared user to update configs', async ()=>{
264
+ prisma.mcpServer.findUnique.mockResolvedValue(server);
265
+ sharingService.getPermission.mockResolvedValue('admin');
266
+ sharingService.isSharedWith.mockResolvedValue(true);
267
+ prisma.mcpServerToolConfig.findMany.mockResolvedValue([
268
+ {
269
+ id: 'tc-1',
270
+ mcpServerId: 'srv-1',
271
+ toolName: 'read_file',
272
+ isEnabled: true
273
+ }
274
+ ]);
275
+ const result = await service.updateServerToolConfigs('srv-1', [
276
+ {
277
+ toolName: 'read_file',
278
+ isEnabled: true
279
+ }
280
+ ], 'user-b');
281
+ expect(result.tools).toBeDefined();
282
+ });
283
+ });
284
+ });
285
+
286
+ //# sourceMappingURL=mcp-server-tool-configs.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/__tests__/unit/mcp-server-tool-configs.test.ts"],"sourcesContent":["/**\n * Tests for McpService — server-level tool configurations (allowlist)\n */\n\nimport { ForbiddenException } from '@nestjs/common';\nimport { beforeEach, describe, expect, it, vi } from 'vitest';\nimport type { PrismaService } from '../../modules/database/prisma.service.js';\nimport type { DebugService } from '../../modules/debug/debug.service.js';\nimport { McpService } from '../../modules/mcp/mcp.service.js';\nimport { McpRegistry } from '../../modules/mcp/mcp-registry.js';\nimport type { SharingService } from '../../modules/sharing/sharing.service.js';\n\n// Mock @dxheroes/local-mcp-core\nconst mockInitialize = vi.fn().mockResolvedValue(undefined);\nconst mockListTools = vi.fn().mockResolvedValue([\n { name: 'read_file', description: 'Read a file' },\n { name: 'write_file', description: 'Write a file' },\n { name: 'delete_file', description: 'Delete a file' },\n]);\nconst mockShutdown = vi.fn().mockResolvedValue(undefined);\n\nvi.mock('@dxheroes/local-mcp-core', async (importOriginal) => {\n const actual = await importOriginal<typeof import('@dxheroes/local-mcp-core')>();\n return {\n ...actual,\n ExternalMcpServer: class MockExternalMcpServer {\n config: unknown;\n constructor(config: unknown) {\n this.config = config;\n }\n initialize = mockInitialize;\n listTools = mockListTools;\n shutdown = mockShutdown;\n },\n RemoteHttpMcpServer: class MockRemoteHttpMcpServer {\n config: unknown;\n constructor(config: unknown) {\n this.config = config;\n }\n initialize = mockInitialize;\n listTools = mockListTools;\n },\n RemoteSseMcpServer: class MockRemoteSseMcpServer {\n config: unknown;\n constructor(config: unknown) {\n this.config = config;\n }\n initialize = mockInitialize;\n listTools = mockListTools;\n },\n };\n});\n\ndescribe('McpService — Tool Configs', () => {\n let service: McpService;\n // biome-ignore lint: test mock\n let prisma: any;\n let registry: McpRegistry;\n let debugService: Record<string, ReturnType<typeof vi.fn>>;\n let sharingService: Record<string, ReturnType<typeof vi.fn>>;\n\n const server = {\n id: 'srv-1',\n name: 'Test Server',\n type: 'remote_http',\n config: '{\"url\":\"https://example.com/mcp\"}',\n apiKeyConfig: null,\n oauthConfig: null,\n userId: 'user-a',\n profiles: [],\n oauthToken: null,\n toolsCache: [],\n };\n\n beforeEach(() => {\n prisma = {\n mcpServer: {\n findMany: vi.fn().mockResolvedValue([]),\n findUnique: vi.fn().mockResolvedValue(null),\n create: vi.fn().mockResolvedValue({ id: 'new-1' }),\n update: vi.fn().mockResolvedValue({}),\n delete: vi.fn().mockResolvedValue(undefined),\n },\n member: {\n findMany: vi.fn().mockResolvedValue([]),\n },\n mcpServerToolsCache: {\n findMany: vi.fn().mockResolvedValue([]),\n },\n mcpServerToolConfig: {\n findMany: vi.fn().mockResolvedValue([]),\n deleteMany: vi.fn().mockResolvedValue({ count: 0 }),\n createMany: vi.fn().mockResolvedValue({ count: 0 }),\n },\n $transaction: vi.fn(async (fn: (tx: unknown) => Promise<unknown>) => {\n return fn(prisma);\n }),\n };\n registry = new McpRegistry();\n debugService = {\n createLog: vi.fn().mockResolvedValue({ id: 'log-1' }),\n updateLog: vi.fn().mockResolvedValue({}),\n };\n sharingService = {\n getSharedResourceIds: vi.fn().mockResolvedValue([]),\n isSharedWith: vi.fn().mockResolvedValue(false),\n getPermission: vi.fn().mockResolvedValue(null),\n };\n service = new McpService(\n prisma as unknown as PrismaService,\n registry,\n debugService as unknown as DebugService,\n sharingService as unknown as SharingService\n );\n });\n\n describe('getServerToolConfigs', () => {\n it('returns all tools as enabled when no configs exist (unconfigured server)', async () => {\n prisma.mcpServer.findUnique.mockResolvedValue(server);\n prisma.mcpServerToolConfig.findMany.mockResolvedValue([]);\n\n const result = await service.getServerToolConfigs('srv-1', 'user-a');\n\n expect(result.hasConfigs).toBe(false);\n expect(result.tools).toHaveLength(3);\n expect(result.tools.every((t: { isEnabled: boolean }) => t.isEnabled)).toBe(true);\n });\n\n it('returns tools with config records using their isEnabled value', async () => {\n prisma.mcpServer.findUnique.mockResolvedValue(server);\n prisma.mcpServerToolConfig.findMany.mockResolvedValue([\n { id: 'tc-1', mcpServerId: 'srv-1', toolName: 'read_file', isEnabled: true },\n { id: 'tc-2', mcpServerId: 'srv-1', toolName: 'write_file', isEnabled: false },\n { id: 'tc-3', mcpServerId: 'srv-1', toolName: 'delete_file', isEnabled: false },\n ]);\n\n const result = await service.getServerToolConfigs('srv-1', 'user-a');\n\n expect(result.hasConfigs).toBe(true);\n expect(result.tools).toHaveLength(3);\n\n const readFile = result.tools.find((t: { name: string }) => t.name === 'read_file');\n const writeFile = result.tools.find((t: { name: string }) => t.name === 'write_file');\n const deleteFile = result.tools.find((t: { name: string }) => t.name === 'delete_file');\n\n expect(readFile?.isEnabled).toBe(true);\n expect(writeFile?.isEnabled).toBe(false);\n expect(deleteFile?.isEnabled).toBe(false);\n });\n\n it('treats new tools (no config record) as disabled when configs exist', async () => {\n prisma.mcpServer.findUnique.mockResolvedValue(server);\n // Only read_file has a config — write_file and delete_file are \"new\"\n prisma.mcpServerToolConfig.findMany.mockResolvedValue([\n { id: 'tc-1', mcpServerId: 'srv-1', toolName: 'read_file', isEnabled: true },\n ]);\n\n const result = await service.getServerToolConfigs('srv-1', 'user-a');\n\n expect(result.hasConfigs).toBe(true);\n\n const readFile = result.tools.find((t: { name: string }) => t.name === 'read_file');\n const writeFile = result.tools.find((t: { name: string }) => t.name === 'write_file');\n const deleteFile = result.tools.find((t: { name: string }) => t.name === 'delete_file');\n\n expect(readFile?.isEnabled).toBe(true);\n expect(readFile?.hasConfig).toBe(true);\n expect(writeFile?.isEnabled).toBe(false);\n expect(writeFile?.hasConfig).toBe(false);\n expect(deleteFile?.isEnabled).toBe(false);\n expect(deleteFile?.hasConfig).toBe(false);\n });\n\n it('throws ForbiddenException for non-owner without sharing', async () => {\n prisma.mcpServer.findUnique.mockResolvedValue(server);\n\n await expect(service.getServerToolConfigs('srv-1', 'user-b')).rejects.toThrow(\n ForbiddenException\n );\n });\n\n it('allows non-owner with sharing to view configs', async () => {\n prisma.mcpServer.findUnique.mockResolvedValue(server);\n sharingService.isSharedWith.mockResolvedValue(true);\n prisma.mcpServerToolConfig.findMany.mockResolvedValue([]);\n\n const result = await service.getServerToolConfigs('srv-1', 'user-b');\n\n expect(result.tools).toHaveLength(3);\n });\n });\n\n describe('updateServerToolConfigs', () => {\n it('creates config records for all tools in a transaction', async () => {\n prisma.mcpServer.findUnique.mockResolvedValue(server);\n prisma.mcpServerToolConfig.findMany.mockResolvedValue([\n { id: 'tc-1', mcpServerId: 'srv-1', toolName: 'read_file', isEnabled: true },\n { id: 'tc-2', mcpServerId: 'srv-1', toolName: 'write_file', isEnabled: false },\n { id: 'tc-3', mcpServerId: 'srv-1', toolName: 'delete_file', isEnabled: false },\n ]);\n\n await service.updateServerToolConfigs(\n 'srv-1',\n [\n { toolName: 'read_file', isEnabled: true },\n { toolName: 'write_file', isEnabled: false },\n { toolName: 'delete_file', isEnabled: false },\n ],\n 'user-a'\n );\n\n expect(prisma.$transaction).toHaveBeenCalled();\n expect(prisma.mcpServerToolConfig.deleteMany).toHaveBeenCalledWith({\n where: { mcpServerId: 'srv-1' },\n });\n expect(prisma.mcpServerToolConfig.createMany).toHaveBeenCalledWith({\n data: [\n { mcpServerId: 'srv-1', toolName: 'read_file', isEnabled: true },\n { mcpServerId: 'srv-1', toolName: 'write_file', isEnabled: false },\n { mcpServerId: 'srv-1', toolName: 'delete_file', isEnabled: false },\n ],\n });\n });\n\n it('throws ForbiddenException for non-owner', async () => {\n prisma.mcpServer.findUnique.mockResolvedValue(server);\n\n await expect(\n service.updateServerToolConfigs(\n 'srv-1',\n [{ toolName: 'read_file', isEnabled: true }],\n 'user-b'\n )\n ).rejects.toThrow(ForbiddenException);\n });\n\n it('allows admin shared user to update configs', async () => {\n prisma.mcpServer.findUnique.mockResolvedValue(server);\n sharingService.getPermission.mockResolvedValue('admin');\n sharingService.isSharedWith.mockResolvedValue(true);\n prisma.mcpServerToolConfig.findMany.mockResolvedValue([\n { id: 'tc-1', mcpServerId: 'srv-1', toolName: 'read_file', isEnabled: true },\n ]);\n\n const result = await service.updateServerToolConfigs(\n 'srv-1',\n [{ toolName: 'read_file', isEnabled: true }],\n 'user-b'\n );\n\n expect(result.tools).toBeDefined();\n });\n });\n});\n"],"names":["ForbiddenException","beforeEach","describe","expect","it","vi","McpService","McpRegistry","mockInitialize","fn","mockResolvedValue","undefined","mockListTools","name","description","mockShutdown","mock","importOriginal","actual","ExternalMcpServer","MockExternalMcpServer","config","initialize","listTools","shutdown","RemoteHttpMcpServer","MockRemoteHttpMcpServer","RemoteSseMcpServer","MockRemoteSseMcpServer","service","prisma","registry","debugService","sharingService","server","id","type","apiKeyConfig","oauthConfig","userId","profiles","oauthToken","toolsCache","mcpServer","findMany","findUnique","create","update","delete","member","mcpServerToolsCache","mcpServerToolConfig","deleteMany","count","createMany","$transaction","createLog","updateLog","getSharedResourceIds","isSharedWith","getPermission","result","getServerToolConfigs","hasConfigs","toBe","tools","toHaveLength","every","t","isEnabled","mcpServerId","toolName","readFile","find","writeFile","deleteFile","hasConfig","rejects","toThrow","updateServerToolConfigs","toHaveBeenCalled","toHaveBeenCalledWith","where","data","toBeDefined"],"mappings":"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"}