4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
6
import { CancellationToken } from '../../../base/common/cancellation.js' ;
7
+ import { MarkdownString } from '../../../base/common/htmlContent.js' ;
7
8
import { Disposable } from '../../../base/common/lifecycle.js' ;
8
9
import { Schemas } from '../../../base/common/network.js' ;
9
10
import { dirname , joinPath } from '../../../base/common/resources.js' ;
10
11
import { uppercaseFirstLetter } from '../../../base/common/strings.js' ;
12
+ import { isString } from '../../../base/common/types.js' ;
11
13
import { URI } from '../../../base/common/uri.js' ;
12
14
import { localize } from '../../../nls.js' ;
13
15
import { IConfigurationService } from '../../configuration/common/configuration.js' ;
@@ -21,17 +23,20 @@ interface IRawGalleryServersResult {
21
23
readonly servers : readonly IRawGalleryMcpServer [ ] ;
22
24
}
23
25
24
-
25
26
interface IRawGalleryMcpServer {
26
- readonly id : string ;
27
+ readonly id ? : string ;
27
28
readonly name : string ;
28
29
readonly description : string ;
29
30
readonly displayName ?: string ;
30
- readonly repository : {
31
+ readonly iconUrl ?: string ;
32
+ readonly iconUrlDark ?: string ;
33
+ readonly iconUrlLight ?: string ;
34
+ readonly codicon ?: string ;
35
+ readonly repository ?: {
31
36
readonly url : string ;
32
37
readonly source : string ;
33
38
} ;
34
- readonly version_detail : {
39
+ readonly version_detail ? : {
35
40
readonly version : string ;
36
41
readonly release_date : string ;
37
42
readonly is_latest : boolean ;
@@ -43,6 +48,7 @@ interface IRawGalleryMcpServer {
43
48
readonly is_verified : boolean ;
44
49
} ;
45
50
readonly package_types ?: readonly PackageType [ ] ;
51
+ readonly manifest ?: IMcpServerManifest ;
46
52
}
47
53
48
54
type RawGalleryMcpServerManifest = IRawGalleryMcpServer & IMcpServerManifest ;
@@ -81,7 +87,26 @@ export class McpGalleryService extends Disposable implements IMcpGalleryService
81
87
return galleryServers ;
82
88
}
83
89
90
+ async getMcpServer ( name : string ) : Promise < IGalleryMcpServer | undefined > {
91
+ const mcpUrl = this . getMcpGalleryUrl ( ) ?? this . productService . extensionsGallery ?. mcpUrl ;
92
+ if ( ! mcpUrl ) {
93
+ return undefined ;
94
+ }
95
+
96
+ const { servers } = await this . fetchGallery ( mcpUrl , CancellationToken . None ) ;
97
+ const server = servers . find ( item => item . name === name ) ;
98
+ return server ? this . toGalleryMcpServer ( server ) : undefined ;
99
+ }
100
+
84
101
async getManifest ( gallery : IGalleryMcpServer , token : CancellationToken ) : Promise < IMcpServerManifest > {
102
+ if ( gallery . manifest ) {
103
+ return gallery . manifest ;
104
+ }
105
+
106
+ if ( ! gallery . manifestUrl ) {
107
+ throw new Error ( `No manifest URL found for ${ gallery . name } ` ) ;
108
+ }
109
+
85
110
const uri = URI . parse ( gallery . manifestUrl ) ;
86
111
if ( uri . scheme === Schemas . file ) {
87
112
try {
@@ -125,6 +150,10 @@ export class McpGalleryService extends Disposable implements IMcpGalleryService
125
150
}
126
151
}
127
152
153
+ if ( uri . authority !== 'raw.githubusercontent.com' ) {
154
+ return new MarkdownString ( localize ( 'readme.viewInBrowser' , "You can find information about this server [here]({0})" , readmeUrl ) ) . value ;
155
+ }
156
+
128
157
const context = await this . requestService . request ( {
129
158
type : 'GET' ,
130
159
url : readmeUrl ,
@@ -149,14 +178,15 @@ export class McpGalleryService extends Disposable implements IMcpGalleryService
149
178
}
150
179
151
180
return {
152
- id : item . id ,
181
+ id : item . id ?? item . name ,
153
182
name : item . name ,
154
183
displayName : item . displayName ?? nameParts [ nameParts . length - 1 ] . split ( '-' ) . map ( s => uppercaseFirstLetter ( s ) ) . join ( ' ' ) ,
155
- url : item . repository . url ,
184
+ url : item . repository ? .url ,
156
185
description : item . description ,
157
- version : item . version_detail . version ,
158
- lastUpdated : Date . parse ( item . version_detail . release_date ) ,
159
- repositoryUrl : item . repository . url ,
186
+ version : item . version_detail ?. version ,
187
+ lastUpdated : item . version_detail ? Date . parse ( item . version_detail . release_date ) : undefined ,
188
+ repositoryUrl : item . repository ?. url ,
189
+ codicon : item . codicon ,
160
190
readmeUrl : item . readmeUrl ,
161
191
manifestUrl : this . getManifestUrl ( item ) ,
162
192
packageTypes : item . package_types ?? [ ] ,
@@ -166,15 +196,19 @@ export class McpGalleryService extends Disposable implements IMcpGalleryService
166
196
link : item . publisher . url ,
167
197
verified : item . publisher . is_verified ,
168
198
} : undefined ,
199
+ manifest : item . manifest
169
200
} ;
170
201
}
171
202
172
- private async fetchGallery ( token : CancellationToken ) : Promise < IRawGalleryServersResult > {
173
- const mcpGalleryUrl = this . getMcpGalleryUrl ( ) ;
203
+ private async fetchGallery ( token : CancellationToken ) : Promise < IRawGalleryServersResult > ;
204
+ private async fetchGallery ( url : string , token : CancellationToken ) : Promise < IRawGalleryServersResult > ;
205
+ private async fetchGallery ( arg1 : any , arg2 ?: any ) : Promise < IRawGalleryServersResult > {
206
+ const mcpGalleryUrl = isString ( arg1 ) ? arg1 : this . getMcpGalleryUrl ( ) ;
174
207
if ( ! mcpGalleryUrl ) {
175
208
return Promise . resolve ( { servers : [ ] } ) ;
176
209
}
177
210
211
+ const token = isString ( arg1 ) ? arg2 : arg1 ;
178
212
const uri = URI . parse ( mcpGalleryUrl ) ;
179
213
if ( uri . scheme === Schemas . file ) {
180
214
try {
@@ -195,16 +229,16 @@ export class McpGalleryService extends Disposable implements IMcpGalleryService
195
229
return result || { servers : [ ] } ;
196
230
}
197
231
198
- private getManifestUrl ( item : IRawGalleryMcpServer ) : string {
232
+ private getManifestUrl ( item : IRawGalleryMcpServer ) : string | undefined {
199
233
const mcpGalleryUrl = this . getMcpGalleryUrl ( ) ;
200
234
201
235
if ( ! mcpGalleryUrl ) {
202
- return item . repository . url ;
236
+ return undefined ;
203
237
}
204
238
205
239
const uri = URI . parse ( mcpGalleryUrl ) ;
206
240
if ( uri . scheme === Schemas . file ) {
207
- return joinPath ( dirname ( uri ) , item . id ) . fsPath ;
241
+ return joinPath ( dirname ( uri ) , item . id ?? item . name ) . fsPath ;
208
242
}
209
243
210
244
return `${ mcpGalleryUrl } /${ item . id } ` ;
0 commit comments