@@ -24,12 +24,121 @@ import {
2424 ListRootsResultSchema ,
2525 RootsListChangedNotificationSchema ,
2626} from './third_party/index.js' ;
27- import { ToolCategory } from './tools/categories.js' ;
27+ import {
28+ ToolCategory ,
29+ labels ,
30+ OFF_BY_DEFAULT_CATEGORIES ,
31+ } from './tools/categories.js' ;
2832import type { DefinedPageTool , ToolDefinition } from './tools/ToolDefinition.js' ;
2933import { pageIdSchema } from './tools/ToolDefinition.js' ;
3034import { createTools } from './tools/tools.js' ;
3135import { VERSION } from './version.js' ;
3236
37+ const CONDITION_TO_FLAG : Record < string , string > = {
38+ computerVision : 'experimentalVision' ,
39+ experimentalMemory : 'experimentalMemory' ,
40+ experimentalInteropTools : 'experimentalInteropTools' ,
41+ screencast : 'experimentalScreencast' ,
42+ experimentalWebmcp : 'experimentalWebmcp' ,
43+ } ;
44+
45+ function buildDisabledMessage (
46+ toolName : string ,
47+ flag : string ,
48+ categoryLabel ?: string ,
49+ ) : string {
50+ const reason = categoryLabel
51+ ? `is in category ${ categoryLabel } which`
52+ : `requires experimental feature ${ flag } and` ;
53+
54+ return `Tool ${ toolName } ${ reason } is currently disabled. Enable it by running chrome-devtools start ${ flag } =true. For more information check the README.` ;
55+ }
56+
57+ function getCategoryStatus (
58+ category : ToolCategory ,
59+ serverArgs : ReturnType < typeof parseArguments > ,
60+ ) : { categoryFlag ?: string ; disabled : boolean } {
61+ const categoryFlag =
62+ category === ToolCategory . IN_PAGE
63+ ? 'categoryInPageTools'
64+ : `category${ category . charAt ( 0 ) . toUpperCase ( ) + category . slice ( 1 ) } ` ;
65+
66+ const flagValue = serverArgs [ categoryFlag ] ;
67+
68+ const isDisabled = OFF_BY_DEFAULT_CATEGORIES . includes ( category )
69+ ? ! flagValue
70+ : flagValue === false ;
71+
72+ if ( isDisabled ) {
73+ return {
74+ categoryFlag,
75+ disabled : true ,
76+ } ;
77+ }
78+
79+ return {
80+ disabled : false ,
81+ } ;
82+ }
83+
84+ function getConditionStatus (
85+ condition : string ,
86+ serverArgs : ReturnType < typeof parseArguments > ,
87+ ) : { conditionFlag ?: string ; disabled : boolean } {
88+ const experimentalFlag = CONDITION_TO_FLAG [ condition ] ;
89+ if ( experimentalFlag && ! serverArgs [ experimentalFlag ] ) {
90+ return { conditionFlag : experimentalFlag , disabled : true } ;
91+ }
92+
93+ return { disabled : false } ;
94+ }
95+
96+ function getToolStatusInfo (
97+ tool : ToolDefinition | DefinedPageTool ,
98+ serverArgs : ReturnType < typeof parseArguments > ,
99+ ) : { disabled : boolean ; reason ?: string } {
100+ const category = tool . annotations . category ;
101+ const categoryCheck = getCategoryStatus ( category , serverArgs ) ;
102+
103+ if ( category && categoryCheck . disabled ) {
104+ if ( ! categoryCheck . categoryFlag ) {
105+ throw new Error (
106+ 'when the category is disabled there should always be a flag set' ,
107+ ) ;
108+ }
109+
110+ return {
111+ disabled : true ,
112+ reason : buildDisabledMessage (
113+ tool . name ,
114+ `--${ categoryCheck . categoryFlag } ` ,
115+ labels [ category ! ] ,
116+ ) ,
117+ } ;
118+ }
119+
120+ for ( const condition of tool . annotations . conditions || [ ] ) {
121+ const conditionCheck = getConditionStatus ( condition , serverArgs ) ;
122+ if ( conditionCheck . disabled ) {
123+ if ( ! conditionCheck . conditionFlag ) {
124+ throw new Error (
125+ 'when the condition is disabled there should always be a flag set' ,
126+ ) ;
127+ }
128+
129+ return {
130+ disabled : true ,
131+ reason : buildDisabledMessage (
132+ tool . name ,
133+ `--${ conditionCheck . conditionFlag } ` ,
134+ ) ,
135+ } ;
136+ }
137+ }
138+
139+ return { disabled : false } ;
140+ }
141+
33142export async function createMcpServer (
34143 serverArgs : ReturnType < typeof parseArguments > ,
35144 options : {
@@ -143,66 +252,15 @@ export async function createMcpServer(
143252 const toolMutex = new Mutex ( ) ;
144253
145254 function registerTool ( tool : ToolDefinition | DefinedPageTool ) : void {
146- if (
147- tool . annotations . category === ToolCategory . EMULATION &&
148- serverArgs . categoryEmulation === false
149- ) {
150- return ;
151- }
152- if (
153- tool . annotations . category === ToolCategory . PERFORMANCE &&
154- serverArgs . categoryPerformance === false
155- ) {
156- return ;
157- }
158- if (
159- tool . annotations . category === ToolCategory . NETWORK &&
160- serverArgs . categoryNetwork === false
161- ) {
162- return ;
163- }
164- if (
165- tool . annotations . category === ToolCategory . EXTENSIONS &&
166- serverArgs . categoryExtensions === false
167- ) {
168- return ;
169- }
170- if (
171- tool . annotations . category === ToolCategory . IN_PAGE &&
172- ! serverArgs . categoryInPageTools
173- ) {
174- return ;
175- }
176- if (
177- tool . annotations . conditions ?. includes ( 'computerVision' ) &&
178- ! serverArgs . experimentalVision
179- ) {
180- return ;
181- }
182- if (
183- tool . annotations . conditions ?. includes ( 'experimentalMemory' ) &&
184- ! serverArgs . experimentalMemory
185- ) {
186- return ;
187- }
188- if (
189- tool . annotations . conditions ?. includes ( 'experimentalInteropTools' ) &&
190- ! serverArgs . experimentalInteropTools
191- ) {
192- return ;
193- }
194- if (
195- tool . annotations . conditions ?. includes ( 'screencast' ) &&
196- ! serverArgs . experimentalScreencast
197- ) {
198- return ;
199- }
200- if (
201- tool . annotations . conditions ?. includes ( 'experimentalWebmcp' ) &&
202- ! serverArgs . experimentalWebmcp
203- ) {
255+ const { disabled, reason : disabledReason } = getToolStatusInfo (
256+ tool ,
257+ serverArgs ,
258+ ) ;
259+
260+ if ( disabled && ! serverArgs . viaCli ) {
204261 return ;
205262 }
263+
206264 const schema =
207265 'pageScoped' in tool &&
208266 tool . pageScoped &&
@@ -219,6 +277,18 @@ export async function createMcpServer(
219277 annotations : tool . annotations ,
220278 } ,
221279 async ( params ) : Promise < CallToolResult > => {
280+ if ( disabledReason ) {
281+ return {
282+ content : [
283+ {
284+ type : 'text' ,
285+ text : disabledReason ,
286+ } ,
287+ ] ,
288+ isError : true ,
289+ } ;
290+ }
291+
222292 const guard = await toolMutex . acquire ( ) ;
223293 const startTime = Date . now ( ) ;
224294 let success = false ;
0 commit comments