Skip to content

Commit 7bac93b

Browse files
author
Lasim
committed
feat(all): add server_count to MCP category schema and responses, view mcp server catalog
1 parent 00f4897 commit 7bac93b

File tree

14 files changed

+401
-61
lines changed

14 files changed

+401
-61
lines changed

services/backend/api-spec.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14848,6 +14848,10 @@
1484814848
"type": "number",
1484914849
"description": "Sort order for display"
1485014850
},
14851+
"server_count": {
14852+
"type": "number",
14853+
"description": "Number of global MCP servers in this category"
14854+
},
1485114855
"created_at": {
1485214856
"type": "string",
1485314857
"format": "date-time",
@@ -14860,6 +14864,7 @@
1486014864
"description",
1486114865
"icon",
1486214866
"sort_order",
14867+
"server_count",
1486314868
"created_at"
1486414869
]
1486514870
},
@@ -15038,6 +15043,10 @@
1503815043
"type": "number",
1503915044
"description": "Sort order for display"
1504015045
},
15046+
"server_count": {
15047+
"type": "number",
15048+
"description": "Number of global MCP servers in this category"
15049+
},
1504115050
"created_at": {
1504215051
"type": "string",
1504315052
"format": "date-time",
@@ -15050,6 +15059,7 @@
1505015059
"description",
1505115060
"icon",
1505215061
"sort_order",
15062+
"server_count",
1505315063
"created_at"
1505415064
]
1505515065
}
@@ -15446,6 +15456,10 @@
1544615456
"type": "number",
1544715457
"description": "Sort order for display"
1544815458
},
15459+
"server_count": {
15460+
"type": "number",
15461+
"description": "Number of global MCP servers in this category"
15462+
},
1544915463
"created_at": {
1545015464
"type": "string",
1545115465
"format": "date-time",
@@ -15458,6 +15472,7 @@
1545815472
"description",
1545915473
"icon",
1546015474
"sort_order",
15475+
"server_count",
1546115476
"created_at"
1546215477
]
1546315478
}

services/backend/api-spec.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10330,6 +10330,9 @@ paths:
1033010330
sort_order:
1033110331
type: number
1033210332
description: Sort order for display
10333+
server_count:
10334+
type: number
10335+
description: Number of global MCP servers in this category
1033310336
created_at:
1033410337
type: string
1033510338
format: date-time
@@ -10340,6 +10343,7 @@ paths:
1034010343
- description
1034110344
- icon
1034210345
- sort_order
10346+
- server_count
1034310347
- created_at
1034410348
description: Array of MCP server categories
1034510349
required:
@@ -10465,6 +10469,9 @@ paths:
1046510469
sort_order:
1046610470
type: number
1046710471
description: Sort order for display
10472+
server_count:
10473+
type: number
10474+
description: Number of global MCP servers in this category
1046810475
created_at:
1046910476
type: string
1047010477
format: date-time
@@ -10475,6 +10482,7 @@ paths:
1047510482
- description
1047610483
- icon
1047710484
- sort_order
10485+
- server_count
1047810486
- created_at
1047910487
required:
1048010488
- success
@@ -10753,6 +10761,9 @@ paths:
1075310761
sort_order:
1075410762
type: number
1075510763
description: Sort order for display
10764+
server_count:
10765+
type: number
10766+
description: Number of global MCP servers in this category
1075610767
created_at:
1075710768
type: string
1075810769
format: date-time
@@ -10763,6 +10774,7 @@ paths:
1076310774
- description
1076410775
- icon
1076510776
- sort_order
10777+
- server_count
1076610778
- created_at
1076710779
required:
1076810780
- success

services/backend/src/routes/mcp/categories/create.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export default async function createCategory(server: FastifyInstance) {
143143
description: newCategory.description ? String(newCategory.description) : null,
144144
icon: newCategory.icon ? String(newCategory.icon) : null,
145145
sort_order: Number(newCategory.sort_order),
146+
server_count: 0,
146147
created_at: newCategory.created_at.toISOString()
147148
}
148149
};

services/backend/src/routes/mcp/categories/list.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export default async function listCategories(server: FastifyInstance) {
9090

9191
const db = getDb();
9292
const categoriesService = new McpCategoriesService(db, server.log);
93-
const categories = await categoriesService.getAllCategories();
93+
const categories = await categoriesService.getAllCategoriesWithServerCount();
9494

9595
const successResponse: ListCategoriesSuccessResponse = {
9696
success: true,
@@ -100,6 +100,7 @@ export default async function listCategories(server: FastifyInstance) {
100100
description: cat.description ? String(cat.description) : null,
101101
icon: cat.icon ? String(cat.icon) : null,
102102
sort_order: Number(cat.sort_order),
103+
server_count: Number(cat.server_count),
103104
created_at: cat.created_at.toISOString()
104105
}))
105106
};

services/backend/src/routes/mcp/categories/schemas.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,17 @@ export const CATEGORY_SCHEMA = {
2828
type: 'number',
2929
description: 'Sort order for display'
3030
},
31+
server_count: {
32+
type: 'number',
33+
description: 'Number of global MCP servers in this category'
34+
},
3135
created_at: {
3236
type: 'string',
3337
format: 'date-time',
3438
description: 'ISO timestamp when the category was created'
3539
}
3640
},
37-
required: ['id', 'name', 'description', 'icon', 'sort_order', 'created_at']
41+
required: ['id', 'name', 'description', 'icon', 'sort_order', 'server_count', 'created_at']
3842
} as const;
3943

4044
// Standard error response schema - used by all category endpoints
@@ -76,6 +80,7 @@ export interface Category {
7680
description: string | null;
7781
icon: string | null;
7882
sort_order: number;
83+
server_count: number;
7984
created_at: string;
8085
}
8186

services/backend/src/routes/mcp/categories/update.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ export default async function updateCategory(server: FastifyInstance) {
159159
description: updatedCategory.description ? String(updatedCategory.description) : null,
160160
icon: updatedCategory.icon ? String(updatedCategory.icon) : null,
161161
sort_order: Number(updatedCategory.sort_order),
162+
server_count: 0,
162163
created_at: updatedCategory.created_at.toISOString()
163164
}
164165
};

services/backend/src/services/mcpCategoriesService.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { eq, asc, and, count } from 'drizzle-orm';
1+
import { eq, asc, and, count, isNull } from 'drizzle-orm';
22
import { getSchema } from '../db/index';
33
import type { AnyDatabase } from '../db';
44
import type { FastifyBaseLogger } from 'fastify';
@@ -23,6 +23,16 @@ export interface FeaturedCategory {
2323
featured_server_count: number;
2424
}
2525

26+
export interface CategoryWithServerCount {
27+
id: string;
28+
name: string;
29+
description: string | null;
30+
icon: string | null;
31+
sort_order: number;
32+
server_count: number;
33+
created_at: Date;
34+
}
35+
2636
export interface CreateMcpCategoryRequest {
2737
name: string;
2838
description?: string;
@@ -219,4 +229,53 @@ export class McpCategoriesService {
219229
featured_server_count: Number(row.featured_server_count)
220230
}));
221231
}
232+
233+
async getAllCategoriesWithServerCount(): Promise<CategoryWithServerCount[]> {
234+
this.logger.debug({
235+
operation: 'get_all_categories_with_server_count'
236+
}, 'Getting all categories with global server count');
237+
238+
const results = await this.db
239+
.select({
240+
id: this.mcpCategories.id,
241+
name: this.mcpCategories.name,
242+
description: this.mcpCategories.description,
243+
icon: this.mcpCategories.icon,
244+
sort_order: this.mcpCategories.sort_order,
245+
created_at: this.mcpCategories.created_at,
246+
server_count: count(this.mcpServers.id)
247+
})
248+
.from(this.mcpCategories)
249+
.leftJoin(
250+
this.mcpServers,
251+
and(
252+
eq(this.mcpServers.category_id, this.mcpCategories.id),
253+
isNull(this.mcpServers.owner_team_id) // Only global servers
254+
)
255+
)
256+
.groupBy(
257+
this.mcpCategories.id,
258+
this.mcpCategories.name,
259+
this.mcpCategories.description,
260+
this.mcpCategories.icon,
261+
this.mcpCategories.sort_order,
262+
this.mcpCategories.created_at
263+
)
264+
.orderBy(asc(this.mcpCategories.sort_order), asc(this.mcpCategories.name));
265+
266+
this.logger.info({
267+
operation: 'get_all_categories_with_server_count',
268+
categoriesFound: results.length
269+
}, 'Retrieved all categories with global server count');
270+
271+
return results.map(row => ({
272+
id: row.id,
273+
name: row.name,
274+
description: row.description,
275+
icon: row.icon,
276+
sort_order: row.sort_order,
277+
server_count: Number(row.server_count),
278+
created_at: row.created_at
279+
}));
280+
}
222281
}

0 commit comments

Comments
 (0)