@mearl/mcp-server 2.17.1 → 2.19.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.
- package/README.md +2 -2
- package/dist/index.js +2 -2
- package/dist/pluginTools.d.ts +1 -1
- package/dist/pluginTools.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
- 🌐 **browser_page_snapshot**: 首次获取页面结构和可交互元素
|
|
15
15
|
- 🔎 **browser_page_inspect**: 查询 DOM 数量、边框盒、计算样式、遮挡、溢出和滚动容器
|
|
16
16
|
- ⚡ **browser_page_click/drag/type/hover/scroll/press/upload**: 执行页面动作,默认内置观察,返回通知、可交互控件、焦点、导航或直接打开的新标签页
|
|
17
|
-
- 🧩 **
|
|
17
|
+
- 🧩 **plugin_invoke**: 调用当前 MCP Server 宿主已注册的 Skill 插件
|
|
18
18
|
|
|
19
19
|
## 浏览器交互工作流
|
|
20
20
|
|
|
@@ -59,7 +59,7 @@ mearl-mcp-configure
|
|
|
59
59
|
把购物车总价改成 150 元测试一下
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
已通过 `@mearl/setup plugin` 注册的 Skill 插件使用固定的 `
|
|
62
|
+
已通过 `@mearl/setup plugin` 注册的 Skill 插件使用固定的 `plugin_invoke` 工具调用:
|
|
63
63
|
|
|
64
64
|
```json
|
|
65
65
|
{
|
package/dist/index.js
CHANGED
|
@@ -46,7 +46,7 @@ var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropD
|
|
|
46
46
|
|
|
47
47
|
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let entry of ctx.seen.entries()){let seen=entry[1];if(schema===entry[0]){extractToDef(entry);continue}if(ctx.external){let ext=ctx.external.registry.get(entry[0])?.id;if(schema!==entry[0]&&ext){extractToDef(entry);continue}}if(ctx.metadataRegistry.get(entry[0])?.id){extractToDef(entry);continue}if(seen.cycle){extractToDef(entry);continue}if(seen.count>1&&ctx.reused==="ref"){extractToDef(entry);continue}}}function finalize(ctx,schema){let root=ctx.seen.get(schema);if(!root)throw new Error("Unprocessed schema. This is a bug in Zod.");let flattenRef=zodSchema=>{let seen=ctx.seen.get(zodSchema);if(seen.ref===null)return;let schema2=seen.def??seen.schema,_cached={...schema2},ref=seen.ref;if(seen.ref=null,ref){flattenRef(ref);let refSeen=ctx.seen.get(ref),refSchema=refSeen.schema;if(refSchema.$ref&&(ctx.target==="draft-07"||ctx.target==="draft-04"||ctx.target==="openapi-3.0")?(schema2.allOf=schema2.allOf??[],schema2.allOf.push(refSchema)):Object.assign(schema2,refSchema),Object.assign(schema2,_cached),zodSchema._zod.parent===ref)for(let key in schema2)key==="$ref"||key==="allOf"||key in _cached||delete schema2[key];if(refSchema.$ref&&refSeen.def)for(let key in schema2)key==="$ref"||key==="allOf"||key in refSeen.def&&JSON.stringify(schema2[key])===JSON.stringify(refSeen.def[key])&&delete schema2[key]}let parent=zodSchema._zod.parent;if(parent&&parent!==ref){flattenRef(parent);let parentSeen=ctx.seen.get(parent);if(parentSeen?.schema.$ref&&(schema2.$ref=parentSeen.schema.$ref,parentSeen.def))for(let key in schema2)key==="$ref"||key==="allOf"||key in parentSeen.def&&JSON.stringify(schema2[key])===JSON.stringify(parentSeen.def[key])&&delete schema2[key]}ctx.override({zodSchema,jsonSchema:schema2,path:seen.path??[]})};for(let entry of[...ctx.seen.entries()].reverse())flattenRef(entry[0]);let result={};if(ctx.target==="draft-2020-12"?result.$schema="https://json-schema.org/draft/2020-12/schema":ctx.target==="draft-07"?result.$schema="http://json-schema.org/draft-07/schema#":ctx.target==="draft-04"?result.$schema="http://json-schema.org/draft-04/schema#":ctx.target,ctx.external?.uri){let id=ctx.external.registry.get(schema)?.id;if(!id)throw new Error("Schema is missing an `id` property");result.$id=ctx.external.uri(id)}Object.assign(result,root.def??root.schema);let defs=ctx.external?.defs??{};for(let entry of ctx.seen.entries()){let seen=entry[1];seen.def&&seen.defId&&(defs[seen.defId]=seen.def)}ctx.external||Object.keys(defs).length>0&&(ctx.target==="draft-2020-12"?result.$defs=defs:result.definitions=defs);try{let finalized=JSON.parse(JSON.stringify(result));return Object.defineProperty(finalized,"~standard",{value:{...schema["~standard"],jsonSchema:{input:createStandardJSONSchemaMethod(schema,"input",ctx.processors),output:createStandardJSONSchemaMethod(schema,"output",ctx.processors)}},enumerable:!1,writable:!1}),finalized}catch{throw new Error("Error converting schema to JSON.")}}function isTransforming(_schema,_ctx){let ctx=_ctx??{seen:new Set};if(ctx.seen.has(_schema))return!1;ctx.seen.add(_schema);let def=_schema._zod.def;if(def.type==="transform")return!0;if(def.type==="array")return isTransforming(def.element,ctx);if(def.type==="set")return isTransforming(def.valueType,ctx);if(def.type==="lazy")return isTransforming(def.getter(),ctx);if(def.type==="promise"||def.type==="optional"||def.type==="nonoptional"||def.type==="nullable"||def.type==="readonly"||def.type==="default"||def.type==="prefault")return isTransforming(def.innerType,ctx);if(def.type==="intersection")return isTransforming(def.left,ctx)||isTransforming(def.right,ctx);if(def.type==="record"||def.type==="map")return isTransforming(def.keyType,ctx)||isTransforming(def.valueType,ctx);if(def.type==="pipe")return isTransforming(def.in,ctx)||isTransforming(def.out,ctx);if(def.type==="object"){for(let key in def.shape)if(isTransforming(def.shape[key],ctx))return!0;return!1}if(def.type==="union"){for(let option of def.options)if(isTransforming(option,ctx))return!0;return!1}if(def.type==="tuple"){for(let item of def.items)if(isTransforming(item,ctx))return!0;return!!(def.rest&&isTransforming(def.rest,ctx))}return!1}var createToJSONSchemaMethod=(schema,processors={})=>params=>{let ctx=initializeContext({...params,processors});return process2(schema,ctx),extractDefs(ctx,schema),finalize(ctx,schema)},createStandardJSONSchemaMethod=(schema,io,processors={})=>params=>{let{libraryOptions,target}=params??{},ctx=initializeContext({...libraryOptions??{},target,io,processors});return process2(schema,ctx),extractDefs(ctx,schema),finalize(ctx,schema)};var formatMap={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},stringProcessor=(schema,ctx,_json,_params)=>{let json2=_json;json2.type="string";let{minimum,maximum,format,patterns,contentEncoding}=schema._zod.bag;if(typeof minimum=="number"&&(json2.minLength=minimum),typeof maximum=="number"&&(json2.maxLength=maximum),format&&(json2.format=formatMap[format]??format,json2.format===""&&delete json2.format,format==="time"&&delete json2.format),contentEncoding&&(json2.contentEncoding=contentEncoding),patterns&&patterns.size>0){let regexes=[...patterns];regexes.length===1?json2.pattern=regexes[0].source:regexes.length>1&&(json2.allOf=[...regexes.map(regex=>({...ctx.target==="draft-07"||ctx.target==="draft-04"||ctx.target==="openapi-3.0"?{type:"string"}:{},pattern:regex.source}))])}},numberProcessor=(schema,ctx,_json,_params)=>{let json2=_json,{minimum,maximum,format,multipleOf,exclusiveMaximum,exclusiveMinimum}=schema._zod.bag;typeof format=="string"&&format.includes("int")?json2.type="integer":json2.type="number",typeof exclusiveMinimum=="number"&&(ctx.target==="draft-04"||ctx.target==="openapi-3.0"?(json2.minimum=exclusiveMinimum,json2.exclusiveMinimum=!0):json2.exclusiveMinimum=exclusiveMinimum),typeof minimum=="number"&&(json2.minimum=minimum,typeof exclusiveMinimum=="number"&&ctx.target!=="draft-04"&&(exclusiveMinimum>=minimum?delete json2.minimum:delete json2.exclusiveMinimum)),typeof exclusiveMaximum=="number"&&(ctx.target==="draft-04"||ctx.target==="openapi-3.0"?(json2.maximum=exclusiveMaximum,json2.exclusiveMaximum=!0):json2.exclusiveMaximum=exclusiveMaximum),typeof maximum=="number"&&(json2.maximum=maximum,typeof exclusiveMaximum=="number"&&ctx.target!=="draft-04"&&(exclusiveMaximum<=maximum?delete json2.maximum:delete json2.exclusiveMaximum)),typeof multipleOf=="number"&&(json2.multipleOf=multipleOf)},booleanProcessor=(_schema,_ctx,json2,_params)=>{json2.type="boolean"},bigintProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("BigInt cannot be represented in JSON Schema")},symbolProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Symbols cannot be represented in JSON Schema")},nullProcessor=(_schema,ctx,json2,_params)=>{ctx.target==="openapi-3.0"?(json2.type="string",json2.nullable=!0,json2.enum=[null]):json2.type="null"},undefinedProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Undefined cannot be represented in JSON Schema")},voidProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Void cannot be represented in JSON Schema")},neverProcessor=(_schema,_ctx,json2,_params)=>{json2.not={}},anyProcessor=(_schema,_ctx,_json,_params)=>{},unknownProcessor=(_schema,_ctx,_json,_params)=>{},dateProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Date cannot be represented in JSON Schema")},enumProcessor=(schema,_ctx,json2,_params)=>{let def=schema._zod.def,values=getEnumValues(def.entries);values.every(v=>typeof v=="number")&&(json2.type="number"),values.every(v=>typeof v=="string")&&(json2.type="string"),json2.enum=values},literalProcessor=(schema,ctx,json2,_params)=>{let def=schema._zod.def,vals=[];for(let val of def.values)if(val===void 0){if(ctx.unrepresentable==="throw")throw new Error("Literal `undefined` cannot be represented in JSON Schema")}else if(typeof val=="bigint"){if(ctx.unrepresentable==="throw")throw new Error("BigInt literals cannot be represented in JSON Schema");vals.push(Number(val))}else vals.push(val);if(vals.length!==0)if(vals.length===1){let val=vals[0];json2.type=val===null?"null":typeof val,ctx.target==="draft-04"||ctx.target==="openapi-3.0"?json2.enum=[val]:json2.const=val}else vals.every(v=>typeof v=="number")&&(json2.type="number"),vals.every(v=>typeof v=="string")&&(json2.type="string"),vals.every(v=>typeof v=="boolean")&&(json2.type="boolean"),vals.every(v=>v===null)&&(json2.type="null"),json2.enum=vals},nanProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("NaN cannot be represented in JSON Schema")},templateLiteralProcessor=(schema,_ctx,json2,_params)=>{let _json=json2,pattern=schema._zod.pattern;if(!pattern)throw new Error("Pattern not found in template literal");_json.type="string",_json.pattern=pattern.source},fileProcessor=(schema,_ctx,json2,_params)=>{let _json=json2,file2={type:"string",format:"binary",contentEncoding:"binary"},{minimum,maximum,mime}=schema._zod.bag;minimum!==void 0&&(file2.minLength=minimum),maximum!==void 0&&(file2.maxLength=maximum),mime?mime.length===1?(file2.contentMediaType=mime[0],Object.assign(_json,file2)):(Object.assign(_json,file2),_json.anyOf=mime.map(m=>({contentMediaType:m}))):Object.assign(_json,file2)},successProcessor=(_schema,_ctx,json2,_params)=>{json2.type="boolean"},customProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},functionProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Function types cannot be represented in JSON Schema")},transformProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},mapProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Map cannot be represented in JSON Schema")},setProcessor=(_schema,ctx,_json,_params)=>{if(ctx.unrepresentable==="throw")throw new Error("Set cannot be represented in JSON Schema")},arrayProcessor=(schema,ctx,_json,params)=>{let json2=_json,def=schema._zod.def,{minimum,maximum}=schema._zod.bag;typeof minimum=="number"&&(json2.minItems=minimum),typeof maximum=="number"&&(json2.maxItems=maximum),json2.type="array",json2.items=process2(def.element,ctx,{...params,path:[...params.path,"items"]})},objectProcessor=(schema,ctx,_json,params)=>{let json2=_json,def=schema._zod.def;json2.type="object",json2.properties={};let shape=def.shape;for(let key in shape)json2.properties[key]=process2(shape[key],ctx,{...params,path:[...params.path,"properties",key]});let allKeys=new Set(Object.keys(shape)),requiredKeys=new Set([...allKeys].filter(key=>{let v=def.shape[key]._zod;return ctx.io==="input"?v.optin===void 0:v.optout===void 0}));requiredKeys.size>0&&(json2.required=Array.from(requiredKeys)),def.catchall?._zod.def.type==="never"?json2.additionalProperties=!1:def.catchall?def.catchall&&(json2.additionalProperties=process2(def.catchall,ctx,{...params,path:[...params.path,"additionalProperties"]})):ctx.io==="output"&&(json2.additionalProperties=!1)},unionProcessor=(schema,ctx,json2,params)=>{let def=schema._zod.def,isExclusive=def.inclusive===!1,options=def.options.map((x,i)=>process2(x,ctx,{...params,path:[...params.path,isExclusive?"oneOf":"anyOf",i]}));isExclusive?json2.oneOf=options:json2.anyOf=options},intersectionProcessor=(schema,ctx,json2,params)=>{let def=schema._zod.def,a=process2(def.left,ctx,{...params,path:[...params.path,"allOf",0]}),b=process2(def.right,ctx,{...params,path:[...params.path,"allOf",1]}),isSimpleIntersection=val=>"allOf"in val&&Object.keys(val).length===1,allOf=[...isSimpleIntersection(a)?a.allOf:[a],...isSimpleIntersection(b)?b.allOf:[b]];json2.allOf=allOf},tupleProcessor=(schema,ctx,_json,params)=>{let json2=_json,def=schema._zod.def;json2.type="array";let prefixPath=ctx.target==="draft-2020-12"?"prefixItems":"items",restPath=ctx.target==="draft-2020-12"||ctx.target==="openapi-3.0"?"items":"additionalItems",prefixItems=def.items.map((x,i)=>process2(x,ctx,{...params,path:[...params.path,prefixPath,i]})),rest=def.rest?process2(def.rest,ctx,{...params,path:[...params.path,restPath,...ctx.target==="openapi-3.0"?[def.items.length]:[]]}):null;ctx.target==="draft-2020-12"?(json2.prefixItems=prefixItems,rest&&(json2.items=rest)):ctx.target==="openapi-3.0"?(json2.items={anyOf:prefixItems},rest&&json2.items.anyOf.push(rest),json2.minItems=prefixItems.length,rest||(json2.maxItems=prefixItems.length)):(json2.items=prefixItems,rest&&(json2.additionalItems=rest));let{minimum,maximum}=schema._zod.bag;typeof minimum=="number"&&(json2.minItems=minimum),typeof maximum=="number"&&(json2.maxItems=maximum)},recordProcessor=(schema,ctx,_json,params)=>{let json2=_json,def=schema._zod.def;json2.type="object";let keyType=def.keyType,patterns=keyType._zod.bag?.patterns;if(def.mode==="loose"&&patterns&&patterns.size>0){let valueSchema=process2(def.valueType,ctx,{...params,path:[...params.path,"patternProperties","*"]});json2.patternProperties={};for(let pattern of patterns)json2.patternProperties[pattern.source]=valueSchema}else(ctx.target==="draft-07"||ctx.target==="draft-2020-12")&&(json2.propertyNames=process2(def.keyType,ctx,{...params,path:[...params.path,"propertyNames"]})),json2.additionalProperties=process2(def.valueType,ctx,{...params,path:[...params.path,"additionalProperties"]});let keyValues=keyType._zod.values;if(keyValues){let validKeyValues=[...keyValues].filter(v=>typeof v=="string"||typeof v=="number");validKeyValues.length>0&&(json2.required=validKeyValues)}},nullableProcessor=(schema,ctx,json2,params)=>{let def=schema._zod.def,inner=process2(def.innerType,ctx,params),seen=ctx.seen.get(schema);ctx.target==="openapi-3.0"?(seen.ref=def.innerType,json2.nullable=!0):json2.anyOf=[inner,{type:"null"}]},nonoptionalProcessor=(schema,ctx,_json,params)=>{let def=schema._zod.def;process2(def.innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=def.innerType},defaultProcessor=(schema,ctx,json2,params)=>{let def=schema._zod.def;process2(def.innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=def.innerType,json2.default=JSON.parse(JSON.stringify(def.defaultValue))},prefaultProcessor=(schema,ctx,json2,params)=>{let def=schema._zod.def;process2(def.innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=def.innerType,ctx.io==="input"&&(json2._prefault=JSON.parse(JSON.stringify(def.defaultValue)))},catchProcessor=(schema,ctx,json2,params)=>{let def=schema._zod.def;process2(def.innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=def.innerType;let catchValue;try{catchValue=def.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}json2.default=catchValue},pipeProcessor=(schema,ctx,_json,params)=>{let def=schema._zod.def,innerType=ctx.io==="input"?def.in._zod.def.type==="transform"?def.out:def.in:def.out;process2(innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=innerType},readonlyProcessor=(schema,ctx,json2,params)=>{let def=schema._zod.def;process2(def.innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=def.innerType,json2.readOnly=!0},promiseProcessor=(schema,ctx,_json,params)=>{let def=schema._zod.def;process2(def.innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=def.innerType},optionalProcessor=(schema,ctx,_json,params)=>{let def=schema._zod.def;process2(def.innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=def.innerType},lazyProcessor=(schema,ctx,_json,params)=>{let innerType=schema._zod.innerType;process2(innerType,ctx,params);let seen=ctx.seen.get(schema);seen.ref=innerType};function isZ4Schema(s){return!!s._zod}function safeParse2(schema,data){return isZ4Schema(schema)?safeParse(schema,data):schema.safeParse(data)}function getObjectShape(schema){if(!schema)return;let rawShape;if(isZ4Schema(schema)?rawShape=schema._zod?.def?.shape:rawShape=schema.shape,!!rawShape){if(typeof rawShape=="function")try{return rawShape()}catch{return}return rawShape}}function getLiteralValue(schema){if(isZ4Schema(schema)){let def2=schema._zod?.def;if(def2){if(def2.value!==void 0)return def2.value;if(Array.isArray(def2.values)&&def2.values.length>0)return def2.values[0]}}let def=schema._def;if(def){if(def.value!==void 0)return def.value;if(Array.isArray(def.values)&&def.values.length>0)return def.values[0]}let directValue=schema.value;if(directValue!==void 0)return directValue}var schemas_exports3={};__export(schemas_exports3,{ZodAny:()=>ZodAny2,ZodArray:()=>ZodArray2,ZodBase64:()=>ZodBase64,ZodBase64URL:()=>ZodBase64URL,ZodBigInt:()=>ZodBigInt2,ZodBigIntFormat:()=>ZodBigIntFormat,ZodBoolean:()=>ZodBoolean2,ZodCIDRv4:()=>ZodCIDRv4,ZodCIDRv6:()=>ZodCIDRv6,ZodCUID:()=>ZodCUID,ZodCUID2:()=>ZodCUID2,ZodCatch:()=>ZodCatch2,ZodCodec:()=>ZodCodec,ZodCustom:()=>ZodCustom,ZodCustomStringFormat:()=>ZodCustomStringFormat,ZodDate:()=>ZodDate2,ZodDefault:()=>ZodDefault2,ZodDiscriminatedUnion:()=>ZodDiscriminatedUnion2,ZodE164:()=>ZodE164,ZodEmail:()=>ZodEmail,ZodEmoji:()=>ZodEmoji,ZodEnum:()=>ZodEnum2,ZodExactOptional:()=>ZodExactOptional,ZodFile:()=>ZodFile,ZodFunction:()=>ZodFunction2,ZodGUID:()=>ZodGUID,ZodIPv4:()=>ZodIPv4,ZodIPv6:()=>ZodIPv6,ZodIntersection:()=>ZodIntersection2,ZodJWT:()=>ZodJWT,ZodKSUID:()=>ZodKSUID,ZodLazy:()=>ZodLazy2,ZodLiteral:()=>ZodLiteral2,ZodMAC:()=>ZodMAC,ZodMap:()=>ZodMap2,ZodNaN:()=>ZodNaN2,ZodNanoID:()=>ZodNanoID,ZodNever:()=>ZodNever2,ZodNonOptional:()=>ZodNonOptional,ZodNull:()=>ZodNull2,ZodNullable:()=>ZodNullable2,ZodNumber:()=>ZodNumber2,ZodNumberFormat:()=>ZodNumberFormat,ZodObject:()=>ZodObject2,ZodOptional:()=>ZodOptional2,ZodPipe:()=>ZodPipe,ZodPrefault:()=>ZodPrefault,ZodPromise:()=>ZodPromise2,ZodReadonly:()=>ZodReadonly2,ZodRecord:()=>ZodRecord2,ZodSet:()=>ZodSet2,ZodString:()=>ZodString2,ZodStringFormat:()=>ZodStringFormat,ZodSuccess:()=>ZodSuccess,ZodSymbol:()=>ZodSymbol2,ZodTemplateLiteral:()=>ZodTemplateLiteral,ZodTransform:()=>ZodTransform,ZodTuple:()=>ZodTuple2,ZodType:()=>ZodType2,ZodULID:()=>ZodULID,ZodURL:()=>ZodURL,ZodUUID:()=>ZodUUID,ZodUndefined:()=>ZodUndefined2,ZodUnion:()=>ZodUnion2,ZodUnknown:()=>ZodUnknown2,ZodVoid:()=>ZodVoid2,ZodXID:()=>ZodXID,ZodXor:()=>ZodXor,_ZodString:()=>_ZodString,_default:()=>_default,_function:()=>_function,any:()=>any,array:()=>array,base64:()=>base642,base64url:()=>base64url2,bigint:()=>bigint2,boolean:()=>boolean2,catch:()=>_catch,check:()=>check,cidrv4:()=>cidrv42,cidrv6:()=>cidrv62,codec:()=>codec,cuid:()=>cuid3,cuid2:()=>cuid22,custom:()=>custom,date:()=>date3,describe:()=>describe2,discriminatedUnion:()=>discriminatedUnion,e164:()=>e1642,email:()=>email2,emoji:()=>emoji2,enum:()=>_enum,exactOptional:()=>exactOptional,file:()=>file,float32:()=>float32,float64:()=>float64,function:()=>_function,guid:()=>guid2,hash:()=>hash,hex:()=>hex2,hostname:()=>hostname2,httpUrl:()=>httpUrl,instanceof:()=>_instanceof,int:()=>int,int32:()=>int32,int64:()=>int64,intersection:()=>intersection,ipv4:()=>ipv42,ipv6:()=>ipv62,json:()=>json,jwt:()=>jwt,keyof:()=>keyof,ksuid:()=>ksuid2,lazy:()=>lazy,literal:()=>literal,looseObject:()=>looseObject,looseRecord:()=>looseRecord,mac:()=>mac2,map:()=>map,meta:()=>meta2,nan:()=>nan,nanoid:()=>nanoid2,nativeEnum:()=>nativeEnum,never:()=>never,nonoptional:()=>nonoptional,null:()=>_null3,nullable:()=>nullable,nullish:()=>nullish2,number:()=>number2,object:()=>object2,optional:()=>optional,partialRecord:()=>partialRecord,pipe:()=>pipe,prefault:()=>prefault,preprocess:()=>preprocess,promise:()=>promise,readonly:()=>readonly,record:()=>record,refine:()=>refine,set:()=>set,strictObject:()=>strictObject,string:()=>string2,stringFormat:()=>stringFormat,stringbool:()=>stringbool,success:()=>success,superRefine:()=>superRefine,symbol:()=>symbol,templateLiteral:()=>templateLiteral,transform:()=>transform,tuple:()=>tuple,uint32:()=>uint32,uint64:()=>uint64,ulid:()=>ulid2,undefined:()=>_undefined3,union:()=>union,unknown:()=>unknown,url:()=>url,uuid:()=>uuid2,uuidv4:()=>uuidv4,uuidv6:()=>uuidv6,uuidv7:()=>uuidv7,void:()=>_void2,xid:()=>xid2,xor:()=>xor});var checks_exports2={};__export(checks_exports2,{endsWith:()=>_endsWith,gt:()=>_gt,gte:()=>_gte,includes:()=>_includes,length:()=>_length,lowercase:()=>_lowercase,lt:()=>_lt,lte:()=>_lte,maxLength:()=>_maxLength,maxSize:()=>_maxSize,mime:()=>_mime,minLength:()=>_minLength,minSize:()=>_minSize,multipleOf:()=>_multipleOf,negative:()=>_negative,nonnegative:()=>_nonnegative,nonpositive:()=>_nonpositive,normalize:()=>_normalize,overwrite:()=>_overwrite,positive:()=>_positive,property:()=>_property,regex:()=>_regex,size:()=>_size,slugify:()=>_slugify,startsWith:()=>_startsWith,toLowerCase:()=>_toLowerCase,toUpperCase:()=>_toUpperCase,trim:()=>_trim,uppercase:()=>_uppercase});var iso_exports2={};__export(iso_exports2,{ZodISODate:()=>ZodISODate,ZodISODateTime:()=>ZodISODateTime,ZodISODuration:()=>ZodISODuration,ZodISOTime:()=>ZodISOTime,date:()=>date2,datetime:()=>datetime2,duration:()=>duration2,time:()=>time2});var ZodISODateTime=$constructor("ZodISODateTime",(inst,def)=>{$ZodISODateTime.init(inst,def),ZodStringFormat.init(inst,def)});function datetime2(params){return _isoDateTime(ZodISODateTime,params)}var ZodISODate=$constructor("ZodISODate",(inst,def)=>{$ZodISODate.init(inst,def),ZodStringFormat.init(inst,def)});function date2(params){return _isoDate(ZodISODate,params)}var ZodISOTime=$constructor("ZodISOTime",(inst,def)=>{$ZodISOTime.init(inst,def),ZodStringFormat.init(inst,def)});function time2(params){return _isoTime(ZodISOTime,params)}var ZodISODuration=$constructor("ZodISODuration",(inst,def)=>{$ZodISODuration.init(inst,def),ZodStringFormat.init(inst,def)});function duration2(params){return _isoDuration(ZodISODuration,params)}var initializer2=(inst,issues)=>{$ZodError.init(inst,issues),inst.name="ZodError",Object.defineProperties(inst,{format:{value:mapper=>formatError(inst,mapper)},flatten:{value:mapper=>flattenError(inst,mapper)},addIssue:{value:issue2=>{inst.issues.push(issue2),inst.message=JSON.stringify(inst.issues,jsonStringifyReplacer,2)}},addIssues:{value:issues2=>{inst.issues.push(...issues2),inst.message=JSON.stringify(inst.issues,jsonStringifyReplacer,2)}},isEmpty:{get(){return inst.issues.length===0}}})},ZodError2=$constructor("ZodError",initializer2),ZodRealError=$constructor("ZodError",initializer2,{Parent:Error});var parse2=_parse(ZodRealError),parseAsync2=_parseAsync(ZodRealError),safeParse3=_safeParse(ZodRealError),safeParseAsync2=_safeParseAsync(ZodRealError),encode2=_encode(ZodRealError),decode2=_decode(ZodRealError),encodeAsync2=_encodeAsync(ZodRealError),decodeAsync2=_decodeAsync(ZodRealError),safeEncode2=_safeEncode(ZodRealError),safeDecode2=_safeDecode(ZodRealError),safeEncodeAsync2=_safeEncodeAsync(ZodRealError),safeDecodeAsync2=_safeDecodeAsync(ZodRealError);var ZodType2=$constructor("ZodType",(inst,def)=>($ZodType.init(inst,def),Object.assign(inst["~standard"],{jsonSchema:{input:createStandardJSONSchemaMethod(inst,"input"),output:createStandardJSONSchemaMethod(inst,"output")}}),inst.toJSONSchema=createToJSONSchemaMethod(inst,{}),inst.def=def,inst.type=def.type,Object.defineProperty(inst,"_def",{value:def}),inst.check=(...checks)=>inst.clone(util_exports.mergeDefs(def,{checks:[...def.checks??[],...checks.map(ch=>typeof ch=="function"?{_zod:{check:ch,def:{check:"custom"},onattach:[]}}:ch)]}),{parent:!0}),inst.with=inst.check,inst.clone=(def2,params)=>clone(inst,def2,params),inst.brand=()=>inst,inst.register=((reg,meta3)=>(reg.add(inst,meta3),inst)),inst.parse=(data,params)=>parse2(inst,data,params,{callee:inst.parse}),inst.safeParse=(data,params)=>safeParse3(inst,data,params),inst.parseAsync=async(data,params)=>parseAsync2(inst,data,params,{callee:inst.parseAsync}),inst.safeParseAsync=async(data,params)=>safeParseAsync2(inst,data,params),inst.spa=inst.safeParseAsync,inst.encode=(data,params)=>encode2(inst,data,params),inst.decode=(data,params)=>decode2(inst,data,params),inst.encodeAsync=async(data,params)=>encodeAsync2(inst,data,params),inst.decodeAsync=async(data,params)=>decodeAsync2(inst,data,params),inst.safeEncode=(data,params)=>safeEncode2(inst,data,params),inst.safeDecode=(data,params)=>safeDecode2(inst,data,params),inst.safeEncodeAsync=async(data,params)=>safeEncodeAsync2(inst,data,params),inst.safeDecodeAsync=async(data,params)=>safeDecodeAsync2(inst,data,params),inst.refine=(check2,params)=>inst.check(refine(check2,params)),inst.superRefine=refinement=>inst.check(superRefine(refinement)),inst.overwrite=fn=>inst.check(_overwrite(fn)),inst.optional=()=>optional(inst),inst.exactOptional=()=>exactOptional(inst),inst.nullable=()=>nullable(inst),inst.nullish=()=>optional(nullable(inst)),inst.nonoptional=params=>nonoptional(inst,params),inst.array=()=>array(inst),inst.or=arg=>union([inst,arg]),inst.and=arg=>intersection(inst,arg),inst.transform=tx=>pipe(inst,transform(tx)),inst.default=def2=>_default(inst,def2),inst.prefault=def2=>prefault(inst,def2),inst.catch=params=>_catch(inst,params),inst.pipe=target=>pipe(inst,target),inst.readonly=()=>readonly(inst),inst.describe=description=>{let cl=inst.clone();return globalRegistry.add(cl,{description}),cl},Object.defineProperty(inst,"description",{get(){return globalRegistry.get(inst)?.description},configurable:!0}),inst.meta=(...args)=>{if(args.length===0)return globalRegistry.get(inst);let cl=inst.clone();return globalRegistry.add(cl,args[0]),cl},inst.isOptional=()=>inst.safeParse(void 0).success,inst.isNullable=()=>inst.safeParse(null).success,inst.apply=fn=>fn(inst),inst)),_ZodString=$constructor("_ZodString",(inst,def)=>{$ZodString.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>stringProcessor(inst,ctx,json2,params);let bag=inst._zod.bag;inst.format=bag.format??null,inst.minLength=bag.minimum??null,inst.maxLength=bag.maximum??null,inst.regex=(...args)=>inst.check(_regex(...args)),inst.includes=(...args)=>inst.check(_includes(...args)),inst.startsWith=(...args)=>inst.check(_startsWith(...args)),inst.endsWith=(...args)=>inst.check(_endsWith(...args)),inst.min=(...args)=>inst.check(_minLength(...args)),inst.max=(...args)=>inst.check(_maxLength(...args)),inst.length=(...args)=>inst.check(_length(...args)),inst.nonempty=(...args)=>inst.check(_minLength(1,...args)),inst.lowercase=params=>inst.check(_lowercase(params)),inst.uppercase=params=>inst.check(_uppercase(params)),inst.trim=()=>inst.check(_trim()),inst.normalize=(...args)=>inst.check(_normalize(...args)),inst.toLowerCase=()=>inst.check(_toLowerCase()),inst.toUpperCase=()=>inst.check(_toUpperCase()),inst.slugify=()=>inst.check(_slugify())}),ZodString2=$constructor("ZodString",(inst,def)=>{$ZodString.init(inst,def),_ZodString.init(inst,def),inst.email=params=>inst.check(_email(ZodEmail,params)),inst.url=params=>inst.check(_url(ZodURL,params)),inst.jwt=params=>inst.check(_jwt(ZodJWT,params)),inst.emoji=params=>inst.check(_emoji2(ZodEmoji,params)),inst.guid=params=>inst.check(_guid(ZodGUID,params)),inst.uuid=params=>inst.check(_uuid(ZodUUID,params)),inst.uuidv4=params=>inst.check(_uuidv4(ZodUUID,params)),inst.uuidv6=params=>inst.check(_uuidv6(ZodUUID,params)),inst.uuidv7=params=>inst.check(_uuidv7(ZodUUID,params)),inst.nanoid=params=>inst.check(_nanoid(ZodNanoID,params)),inst.guid=params=>inst.check(_guid(ZodGUID,params)),inst.cuid=params=>inst.check(_cuid(ZodCUID,params)),inst.cuid2=params=>inst.check(_cuid2(ZodCUID2,params)),inst.ulid=params=>inst.check(_ulid(ZodULID,params)),inst.base64=params=>inst.check(_base64(ZodBase64,params)),inst.base64url=params=>inst.check(_base64url(ZodBase64URL,params)),inst.xid=params=>inst.check(_xid(ZodXID,params)),inst.ksuid=params=>inst.check(_ksuid(ZodKSUID,params)),inst.ipv4=params=>inst.check(_ipv4(ZodIPv4,params)),inst.ipv6=params=>inst.check(_ipv6(ZodIPv6,params)),inst.cidrv4=params=>inst.check(_cidrv4(ZodCIDRv4,params)),inst.cidrv6=params=>inst.check(_cidrv6(ZodCIDRv6,params)),inst.e164=params=>inst.check(_e164(ZodE164,params)),inst.datetime=params=>inst.check(datetime2(params)),inst.date=params=>inst.check(date2(params)),inst.time=params=>inst.check(time2(params)),inst.duration=params=>inst.check(duration2(params))});function string2(params){return _string(ZodString2,params)}var ZodStringFormat=$constructor("ZodStringFormat",(inst,def)=>{$ZodStringFormat.init(inst,def),_ZodString.init(inst,def)}),ZodEmail=$constructor("ZodEmail",(inst,def)=>{$ZodEmail.init(inst,def),ZodStringFormat.init(inst,def)});function email2(params){return _email(ZodEmail,params)}var ZodGUID=$constructor("ZodGUID",(inst,def)=>{$ZodGUID.init(inst,def),ZodStringFormat.init(inst,def)});function guid2(params){return _guid(ZodGUID,params)}var ZodUUID=$constructor("ZodUUID",(inst,def)=>{$ZodUUID.init(inst,def),ZodStringFormat.init(inst,def)});function uuid2(params){return _uuid(ZodUUID,params)}function uuidv4(params){return _uuidv4(ZodUUID,params)}function uuidv6(params){return _uuidv6(ZodUUID,params)}function uuidv7(params){return _uuidv7(ZodUUID,params)}var ZodURL=$constructor("ZodURL",(inst,def)=>{$ZodURL.init(inst,def),ZodStringFormat.init(inst,def)});function url(params){return _url(ZodURL,params)}function httpUrl(params){return _url(ZodURL,{protocol:/^https?$/,hostname:regexes_exports.domain,...util_exports.normalizeParams(params)})}var ZodEmoji=$constructor("ZodEmoji",(inst,def)=>{$ZodEmoji.init(inst,def),ZodStringFormat.init(inst,def)});function emoji2(params){return _emoji2(ZodEmoji,params)}var ZodNanoID=$constructor("ZodNanoID",(inst,def)=>{$ZodNanoID.init(inst,def),ZodStringFormat.init(inst,def)});function nanoid2(params){return _nanoid(ZodNanoID,params)}var ZodCUID=$constructor("ZodCUID",(inst,def)=>{$ZodCUID.init(inst,def),ZodStringFormat.init(inst,def)});function cuid3(params){return _cuid(ZodCUID,params)}var ZodCUID2=$constructor("ZodCUID2",(inst,def)=>{$ZodCUID2.init(inst,def),ZodStringFormat.init(inst,def)});function cuid22(params){return _cuid2(ZodCUID2,params)}var ZodULID=$constructor("ZodULID",(inst,def)=>{$ZodULID.init(inst,def),ZodStringFormat.init(inst,def)});function ulid2(params){return _ulid(ZodULID,params)}var ZodXID=$constructor("ZodXID",(inst,def)=>{$ZodXID.init(inst,def),ZodStringFormat.init(inst,def)});function xid2(params){return _xid(ZodXID,params)}var ZodKSUID=$constructor("ZodKSUID",(inst,def)=>{$ZodKSUID.init(inst,def),ZodStringFormat.init(inst,def)});function ksuid2(params){return _ksuid(ZodKSUID,params)}var ZodIPv4=$constructor("ZodIPv4",(inst,def)=>{$ZodIPv4.init(inst,def),ZodStringFormat.init(inst,def)});function ipv42(params){return _ipv4(ZodIPv4,params)}var ZodMAC=$constructor("ZodMAC",(inst,def)=>{$ZodMAC.init(inst,def),ZodStringFormat.init(inst,def)});function mac2(params){return _mac(ZodMAC,params)}var ZodIPv6=$constructor("ZodIPv6",(inst,def)=>{$ZodIPv6.init(inst,def),ZodStringFormat.init(inst,def)});function ipv62(params){return _ipv6(ZodIPv6,params)}var ZodCIDRv4=$constructor("ZodCIDRv4",(inst,def)=>{$ZodCIDRv4.init(inst,def),ZodStringFormat.init(inst,def)});function cidrv42(params){return _cidrv4(ZodCIDRv4,params)}var ZodCIDRv6=$constructor("ZodCIDRv6",(inst,def)=>{$ZodCIDRv6.init(inst,def),ZodStringFormat.init(inst,def)});function cidrv62(params){return _cidrv6(ZodCIDRv6,params)}var ZodBase64=$constructor("ZodBase64",(inst,def)=>{$ZodBase64.init(inst,def),ZodStringFormat.init(inst,def)});function base642(params){return _base64(ZodBase64,params)}var ZodBase64URL=$constructor("ZodBase64URL",(inst,def)=>{$ZodBase64URL.init(inst,def),ZodStringFormat.init(inst,def)});function base64url2(params){return _base64url(ZodBase64URL,params)}var ZodE164=$constructor("ZodE164",(inst,def)=>{$ZodE164.init(inst,def),ZodStringFormat.init(inst,def)});function e1642(params){return _e164(ZodE164,params)}var ZodJWT=$constructor("ZodJWT",(inst,def)=>{$ZodJWT.init(inst,def),ZodStringFormat.init(inst,def)});function jwt(params){return _jwt(ZodJWT,params)}var ZodCustomStringFormat=$constructor("ZodCustomStringFormat",(inst,def)=>{$ZodCustomStringFormat.init(inst,def),ZodStringFormat.init(inst,def)});function stringFormat(format,fnOrRegex,_params={}){return _stringFormat(ZodCustomStringFormat,format,fnOrRegex,_params)}function hostname2(_params){return _stringFormat(ZodCustomStringFormat,"hostname",regexes_exports.hostname,_params)}function hex2(_params){return _stringFormat(ZodCustomStringFormat,"hex",regexes_exports.hex,_params)}function hash(alg,params){let enc=params?.enc??"hex",format=`${alg}_${enc}`,regex=regexes_exports[format];if(!regex)throw new Error(`Unrecognized hash format: ${format}`);return _stringFormat(ZodCustomStringFormat,format,regex,params)}var ZodNumber2=$constructor("ZodNumber",(inst,def)=>{$ZodNumber.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>numberProcessor(inst,ctx,json2,params),inst.gt=(value,params)=>inst.check(_gt(value,params)),inst.gte=(value,params)=>inst.check(_gte(value,params)),inst.min=(value,params)=>inst.check(_gte(value,params)),inst.lt=(value,params)=>inst.check(_lt(value,params)),inst.lte=(value,params)=>inst.check(_lte(value,params)),inst.max=(value,params)=>inst.check(_lte(value,params)),inst.int=params=>inst.check(int(params)),inst.safe=params=>inst.check(int(params)),inst.positive=params=>inst.check(_gt(0,params)),inst.nonnegative=params=>inst.check(_gte(0,params)),inst.negative=params=>inst.check(_lt(0,params)),inst.nonpositive=params=>inst.check(_lte(0,params)),inst.multipleOf=(value,params)=>inst.check(_multipleOf(value,params)),inst.step=(value,params)=>inst.check(_multipleOf(value,params)),inst.finite=()=>inst;let bag=inst._zod.bag;inst.minValue=Math.max(bag.minimum??Number.NEGATIVE_INFINITY,bag.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,inst.maxValue=Math.min(bag.maximum??Number.POSITIVE_INFINITY,bag.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,inst.isInt=(bag.format??"").includes("int")||Number.isSafeInteger(bag.multipleOf??.5),inst.isFinite=!0,inst.format=bag.format??null});function number2(params){return _number(ZodNumber2,params)}var ZodNumberFormat=$constructor("ZodNumberFormat",(inst,def)=>{$ZodNumberFormat.init(inst,def),ZodNumber2.init(inst,def)});function int(params){return _int(ZodNumberFormat,params)}function float32(params){return _float32(ZodNumberFormat,params)}function float64(params){return _float64(ZodNumberFormat,params)}function int32(params){return _int32(ZodNumberFormat,params)}function uint32(params){return _uint32(ZodNumberFormat,params)}var ZodBoolean2=$constructor("ZodBoolean",(inst,def)=>{$ZodBoolean.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>booleanProcessor(inst,ctx,json2,params)});function boolean2(params){return _boolean(ZodBoolean2,params)}var ZodBigInt2=$constructor("ZodBigInt",(inst,def)=>{$ZodBigInt.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>bigintProcessor(inst,ctx,json2,params),inst.gte=(value,params)=>inst.check(_gte(value,params)),inst.min=(value,params)=>inst.check(_gte(value,params)),inst.gt=(value,params)=>inst.check(_gt(value,params)),inst.gte=(value,params)=>inst.check(_gte(value,params)),inst.min=(value,params)=>inst.check(_gte(value,params)),inst.lt=(value,params)=>inst.check(_lt(value,params)),inst.lte=(value,params)=>inst.check(_lte(value,params)),inst.max=(value,params)=>inst.check(_lte(value,params)),inst.positive=params=>inst.check(_gt(BigInt(0),params)),inst.negative=params=>inst.check(_lt(BigInt(0),params)),inst.nonpositive=params=>inst.check(_lte(BigInt(0),params)),inst.nonnegative=params=>inst.check(_gte(BigInt(0),params)),inst.multipleOf=(value,params)=>inst.check(_multipleOf(value,params));let bag=inst._zod.bag;inst.minValue=bag.minimum??null,inst.maxValue=bag.maximum??null,inst.format=bag.format??null});function bigint2(params){return _bigint(ZodBigInt2,params)}var ZodBigIntFormat=$constructor("ZodBigIntFormat",(inst,def)=>{$ZodBigIntFormat.init(inst,def),ZodBigInt2.init(inst,def)});function int64(params){return _int64(ZodBigIntFormat,params)}function uint64(params){return _uint64(ZodBigIntFormat,params)}var ZodSymbol2=$constructor("ZodSymbol",(inst,def)=>{$ZodSymbol.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>symbolProcessor(inst,ctx,json2,params)});function symbol(params){return _symbol(ZodSymbol2,params)}var ZodUndefined2=$constructor("ZodUndefined",(inst,def)=>{$ZodUndefined.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>undefinedProcessor(inst,ctx,json2,params)});function _undefined3(params){return _undefined2(ZodUndefined2,params)}var ZodNull2=$constructor("ZodNull",(inst,def)=>{$ZodNull.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>nullProcessor(inst,ctx,json2,params)});function _null3(params){return _null2(ZodNull2,params)}var ZodAny2=$constructor("ZodAny",(inst,def)=>{$ZodAny.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>anyProcessor(inst,ctx,json2,params)});function any(){return _any(ZodAny2)}var ZodUnknown2=$constructor("ZodUnknown",(inst,def)=>{$ZodUnknown.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>unknownProcessor(inst,ctx,json2,params)});function unknown(){return _unknown(ZodUnknown2)}var ZodNever2=$constructor("ZodNever",(inst,def)=>{$ZodNever.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>neverProcessor(inst,ctx,json2,params)});function never(params){return _never(ZodNever2,params)}var ZodVoid2=$constructor("ZodVoid",(inst,def)=>{$ZodVoid.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>voidProcessor(inst,ctx,json2,params)});function _void2(params){return _void(ZodVoid2,params)}var ZodDate2=$constructor("ZodDate",(inst,def)=>{$ZodDate.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>dateProcessor(inst,ctx,json2,params),inst.min=(value,params)=>inst.check(_gte(value,params)),inst.max=(value,params)=>inst.check(_lte(value,params));let c=inst._zod.bag;inst.minDate=c.minimum?new Date(c.minimum):null,inst.maxDate=c.maximum?new Date(c.maximum):null});function date3(params){return _date(ZodDate2,params)}var ZodArray2=$constructor("ZodArray",(inst,def)=>{$ZodArray.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>arrayProcessor(inst,ctx,json2,params),inst.element=def.element,inst.min=(minLength,params)=>inst.check(_minLength(minLength,params)),inst.nonempty=params=>inst.check(_minLength(1,params)),inst.max=(maxLength,params)=>inst.check(_maxLength(maxLength,params)),inst.length=(len,params)=>inst.check(_length(len,params)),inst.unwrap=()=>inst.element});function array(element,params){return _array(ZodArray2,element,params)}function keyof(schema){let shape=schema._zod.def.shape;return _enum(Object.keys(shape))}var ZodObject2=$constructor("ZodObject",(inst,def)=>{$ZodObjectJIT.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>objectProcessor(inst,ctx,json2,params),util_exports.defineLazy(inst,"shape",()=>def.shape),inst.keyof=()=>_enum(Object.keys(inst._zod.def.shape)),inst.catchall=catchall=>inst.clone({...inst._zod.def,catchall}),inst.passthrough=()=>inst.clone({...inst._zod.def,catchall:unknown()}),inst.loose=()=>inst.clone({...inst._zod.def,catchall:unknown()}),inst.strict=()=>inst.clone({...inst._zod.def,catchall:never()}),inst.strip=()=>inst.clone({...inst._zod.def,catchall:void 0}),inst.extend=incoming=>util_exports.extend(inst,incoming),inst.safeExtend=incoming=>util_exports.safeExtend(inst,incoming),inst.merge=other=>util_exports.merge(inst,other),inst.pick=mask=>util_exports.pick(inst,mask),inst.omit=mask=>util_exports.omit(inst,mask),inst.partial=(...args)=>util_exports.partial(ZodOptional2,inst,args[0]),inst.required=(...args)=>util_exports.required(ZodNonOptional,inst,args[0])});function object2(shape,params){let def={type:"object",shape:shape??{},...util_exports.normalizeParams(params)};return new ZodObject2(def)}function strictObject(shape,params){return new ZodObject2({type:"object",shape,catchall:never(),...util_exports.normalizeParams(params)})}function looseObject(shape,params){return new ZodObject2({type:"object",shape,catchall:unknown(),...util_exports.normalizeParams(params)})}var ZodUnion2=$constructor("ZodUnion",(inst,def)=>{$ZodUnion.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>unionProcessor(inst,ctx,json2,params),inst.options=def.options});function union(options,params){return new ZodUnion2({type:"union",options,...util_exports.normalizeParams(params)})}var ZodXor=$constructor("ZodXor",(inst,def)=>{ZodUnion2.init(inst,def),$ZodXor.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>unionProcessor(inst,ctx,json2,params),inst.options=def.options});function xor(options,params){return new ZodXor({type:"union",options,inclusive:!1,...util_exports.normalizeParams(params)})}var ZodDiscriminatedUnion2=$constructor("ZodDiscriminatedUnion",(inst,def)=>{ZodUnion2.init(inst,def),$ZodDiscriminatedUnion.init(inst,def)});function discriminatedUnion(discriminator,options,params){return new ZodDiscriminatedUnion2({type:"union",options,discriminator,...util_exports.normalizeParams(params)})}var ZodIntersection2=$constructor("ZodIntersection",(inst,def)=>{$ZodIntersection.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>intersectionProcessor(inst,ctx,json2,params)});function intersection(left,right){return new ZodIntersection2({type:"intersection",left,right})}var ZodTuple2=$constructor("ZodTuple",(inst,def)=>{$ZodTuple.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>tupleProcessor(inst,ctx,json2,params),inst.rest=rest=>inst.clone({...inst._zod.def,rest})});function tuple(items,_paramsOrRest,_params){let hasRest=_paramsOrRest instanceof $ZodType,params=hasRest?_params:_paramsOrRest,rest=hasRest?_paramsOrRest:null;return new ZodTuple2({type:"tuple",items,rest,...util_exports.normalizeParams(params)})}var ZodRecord2=$constructor("ZodRecord",(inst,def)=>{$ZodRecord.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>recordProcessor(inst,ctx,json2,params),inst.keyType=def.keyType,inst.valueType=def.valueType});function record(keyType,valueType,params){return new ZodRecord2({type:"record",keyType,valueType,...util_exports.normalizeParams(params)})}function partialRecord(keyType,valueType,params){let k=clone(keyType);return k._zod.values=void 0,new ZodRecord2({type:"record",keyType:k,valueType,...util_exports.normalizeParams(params)})}function looseRecord(keyType,valueType,params){return new ZodRecord2({type:"record",keyType,valueType,mode:"loose",...util_exports.normalizeParams(params)})}var ZodMap2=$constructor("ZodMap",(inst,def)=>{$ZodMap.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>mapProcessor(inst,ctx,json2,params),inst.keyType=def.keyType,inst.valueType=def.valueType,inst.min=(...args)=>inst.check(_minSize(...args)),inst.nonempty=params=>inst.check(_minSize(1,params)),inst.max=(...args)=>inst.check(_maxSize(...args)),inst.size=(...args)=>inst.check(_size(...args))});function map(keyType,valueType,params){return new ZodMap2({type:"map",keyType,valueType,...util_exports.normalizeParams(params)})}var ZodSet2=$constructor("ZodSet",(inst,def)=>{$ZodSet.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>setProcessor(inst,ctx,json2,params),inst.min=(...args)=>inst.check(_minSize(...args)),inst.nonempty=params=>inst.check(_minSize(1,params)),inst.max=(...args)=>inst.check(_maxSize(...args)),inst.size=(...args)=>inst.check(_size(...args))});function set(valueType,params){return new ZodSet2({type:"set",valueType,...util_exports.normalizeParams(params)})}var ZodEnum2=$constructor("ZodEnum",(inst,def)=>{$ZodEnum.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>enumProcessor(inst,ctx,json2,params),inst.enum=def.entries,inst.options=Object.values(def.entries);let keys=new Set(Object.keys(def.entries));inst.extract=(values,params)=>{let newEntries={};for(let value of values)if(keys.has(value))newEntries[value]=def.entries[value];else throw new Error(`Key ${value} not found in enum`);return new ZodEnum2({...def,checks:[],...util_exports.normalizeParams(params),entries:newEntries})},inst.exclude=(values,params)=>{let newEntries={...def.entries};for(let value of values)if(keys.has(value))delete newEntries[value];else throw new Error(`Key ${value} not found in enum`);return new ZodEnum2({...def,checks:[],...util_exports.normalizeParams(params),entries:newEntries})}});function _enum(values,params){let entries=Array.isArray(values)?Object.fromEntries(values.map(v=>[v,v])):values;return new ZodEnum2({type:"enum",entries,...util_exports.normalizeParams(params)})}function nativeEnum(entries,params){return new ZodEnum2({type:"enum",entries,...util_exports.normalizeParams(params)})}var ZodLiteral2=$constructor("ZodLiteral",(inst,def)=>{$ZodLiteral.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>literalProcessor(inst,ctx,json2,params),inst.values=new Set(def.values),Object.defineProperty(inst,"value",{get(){if(def.values.length>1)throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");return def.values[0]}})});function literal(value,params){return new ZodLiteral2({type:"literal",values:Array.isArray(value)?value:[value],...util_exports.normalizeParams(params)})}var ZodFile=$constructor("ZodFile",(inst,def)=>{$ZodFile.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>fileProcessor(inst,ctx,json2,params),inst.min=(size,params)=>inst.check(_minSize(size,params)),inst.max=(size,params)=>inst.check(_maxSize(size,params)),inst.mime=(types,params)=>inst.check(_mime(Array.isArray(types)?types:[types],params))});function file(params){return _file(ZodFile,params)}var ZodTransform=$constructor("ZodTransform",(inst,def)=>{$ZodTransform.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>transformProcessor(inst,ctx,json2,params),inst._zod.parse=(payload,_ctx)=>{if(_ctx.direction==="backward")throw new $ZodEncodeError(inst.constructor.name);payload.addIssue=issue2=>{if(typeof issue2=="string")payload.issues.push(util_exports.issue(issue2,payload.value,def));else{let _issue=issue2;_issue.fatal&&(_issue.continue=!1),_issue.code??(_issue.code="custom"),_issue.input??(_issue.input=payload.value),_issue.inst??(_issue.inst=inst),payload.issues.push(util_exports.issue(_issue))}};let output=def.transform(payload.value,payload);return output instanceof Promise?output.then(output2=>(payload.value=output2,payload)):(payload.value=output,payload)}});function transform(fn){return new ZodTransform({type:"transform",transform:fn})}var ZodOptional2=$constructor("ZodOptional",(inst,def)=>{$ZodOptional.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>optionalProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType});function optional(innerType){return new ZodOptional2({type:"optional",innerType})}var ZodExactOptional=$constructor("ZodExactOptional",(inst,def)=>{$ZodExactOptional.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>optionalProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType});function exactOptional(innerType){return new ZodExactOptional({type:"optional",innerType})}var ZodNullable2=$constructor("ZodNullable",(inst,def)=>{$ZodNullable.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>nullableProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType});function nullable(innerType){return new ZodNullable2({type:"nullable",innerType})}function nullish2(innerType){return optional(nullable(innerType))}var ZodDefault2=$constructor("ZodDefault",(inst,def)=>{$ZodDefault.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>defaultProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType,inst.removeDefault=inst.unwrap});function _default(innerType,defaultValue){return new ZodDefault2({type:"default",innerType,get defaultValue(){return typeof defaultValue=="function"?defaultValue():util_exports.shallowClone(defaultValue)}})}var ZodPrefault=$constructor("ZodPrefault",(inst,def)=>{$ZodPrefault.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>prefaultProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType});function prefault(innerType,defaultValue){return new ZodPrefault({type:"prefault",innerType,get defaultValue(){return typeof defaultValue=="function"?defaultValue():util_exports.shallowClone(defaultValue)}})}var ZodNonOptional=$constructor("ZodNonOptional",(inst,def)=>{$ZodNonOptional.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>nonoptionalProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType});function nonoptional(innerType,params){return new ZodNonOptional({type:"nonoptional",innerType,...util_exports.normalizeParams(params)})}var ZodSuccess=$constructor("ZodSuccess",(inst,def)=>{$ZodSuccess.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>successProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType});function success(innerType){return new ZodSuccess({type:"success",innerType})}var ZodCatch2=$constructor("ZodCatch",(inst,def)=>{$ZodCatch.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>catchProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType,inst.removeCatch=inst.unwrap});function _catch(innerType,catchValue){return new ZodCatch2({type:"catch",innerType,catchValue:typeof catchValue=="function"?catchValue:()=>catchValue})}var ZodNaN2=$constructor("ZodNaN",(inst,def)=>{$ZodNaN.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>nanProcessor(inst,ctx,json2,params)});function nan(params){return _nan(ZodNaN2,params)}var ZodPipe=$constructor("ZodPipe",(inst,def)=>{$ZodPipe.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>pipeProcessor(inst,ctx,json2,params),inst.in=def.in,inst.out=def.out});function pipe(in_,out){return new ZodPipe({type:"pipe",in:in_,out})}var ZodCodec=$constructor("ZodCodec",(inst,def)=>{ZodPipe.init(inst,def),$ZodCodec.init(inst,def)});function codec(in_,out,params){return new ZodCodec({type:"pipe",in:in_,out,transform:params.decode,reverseTransform:params.encode})}var ZodReadonly2=$constructor("ZodReadonly",(inst,def)=>{$ZodReadonly.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>readonlyProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType});function readonly(innerType){return new ZodReadonly2({type:"readonly",innerType})}var ZodTemplateLiteral=$constructor("ZodTemplateLiteral",(inst,def)=>{$ZodTemplateLiteral.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>templateLiteralProcessor(inst,ctx,json2,params)});function templateLiteral(parts,params){return new ZodTemplateLiteral({type:"template_literal",parts,...util_exports.normalizeParams(params)})}var ZodLazy2=$constructor("ZodLazy",(inst,def)=>{$ZodLazy.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>lazyProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.getter()});function lazy(getter){return new ZodLazy2({type:"lazy",getter})}var ZodPromise2=$constructor("ZodPromise",(inst,def)=>{$ZodPromise.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>promiseProcessor(inst,ctx,json2,params),inst.unwrap=()=>inst._zod.def.innerType});function promise(innerType){return new ZodPromise2({type:"promise",innerType})}var ZodFunction2=$constructor("ZodFunction",(inst,def)=>{$ZodFunction.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>functionProcessor(inst,ctx,json2,params)});function _function(params){return new ZodFunction2({type:"function",input:Array.isArray(params?.input)?tuple(params?.input):params?.input??array(unknown()),output:params?.output??unknown()})}var ZodCustom=$constructor("ZodCustom",(inst,def)=>{$ZodCustom.init(inst,def),ZodType2.init(inst,def),inst._zod.processJSONSchema=(ctx,json2,params)=>customProcessor(inst,ctx,json2,params)});function check(fn){let ch=new $ZodCheck({check:"custom"});return ch._zod.check=fn,ch}function custom(fn,_params){return _custom(ZodCustom,fn??(()=>!0),_params)}function refine(fn,_params={}){return _refine(ZodCustom,fn,_params)}function superRefine(fn){return _superRefine(fn)}var describe2=describe,meta2=meta;function _instanceof(cls,params={}){let inst=new ZodCustom({type:"custom",check:"custom",fn:data=>data instanceof cls,abort:!0,...util_exports.normalizeParams(params)});return inst._zod.bag.Class=cls,inst._zod.check=payload=>{payload.value instanceof cls||payload.issues.push({code:"invalid_type",expected:cls.name,input:payload.value,inst,path:[...inst._zod.def.path??[]]})},inst}var stringbool=(...args)=>_stringbool({Codec:ZodCodec,Boolean:ZodBoolean2,String:ZodString2},...args);function json(params){let jsonSchema=lazy(()=>union([string2(params),number2(),boolean2(),_null3(),array(jsonSchema),record(string2(),jsonSchema)]));return jsonSchema}function preprocess(fn,schema){return pipe(transform(fn),schema)}var ZodFirstPartyTypeKind2;ZodFirstPartyTypeKind2||(ZodFirstPartyTypeKind2={});var z={...schemas_exports3,...checks_exports2,iso:iso_exports2};config(en_default2());var LATEST_PROTOCOL_VERSION="2025-11-25";var SUPPORTED_PROTOCOL_VERSIONS=[LATEST_PROTOCOL_VERSION,"2025-06-18","2025-03-26","2024-11-05","2024-10-07"],RELATED_TASK_META_KEY="io.modelcontextprotocol/related-task",JSONRPC_VERSION="2.0",AssertObjectSchema=custom(v=>v!==null&&(typeof v=="object"||typeof v=="function")),ProgressTokenSchema=union([string2(),number2().int()]),CursorSchema=string2(),TaskCreationParamsSchema=looseObject({ttl:union([number2(),_null3()]).optional(),pollInterval:number2().optional()}),TaskMetadataSchema=object2({ttl:number2().optional()}),RelatedTaskMetadataSchema=object2({taskId:string2()}),RequestMetaSchema=looseObject({progressToken:ProgressTokenSchema.optional(),[RELATED_TASK_META_KEY]:RelatedTaskMetadataSchema.optional()}),BaseRequestParamsSchema=object2({_meta:RequestMetaSchema.optional()}),TaskAugmentedRequestParamsSchema=BaseRequestParamsSchema.extend({task:TaskMetadataSchema.optional()}),isTaskAugmentedRequestParams=value=>TaskAugmentedRequestParamsSchema.safeParse(value).success,RequestSchema=object2({method:string2(),params:BaseRequestParamsSchema.loose().optional()}),NotificationsParamsSchema=object2({_meta:RequestMetaSchema.optional()}),NotificationSchema=object2({method:string2(),params:NotificationsParamsSchema.loose().optional()}),ResultSchema=looseObject({_meta:RequestMetaSchema.optional()}),RequestIdSchema=union([string2(),number2().int()]),JSONRPCRequestSchema=object2({jsonrpc:literal(JSONRPC_VERSION),id:RequestIdSchema,...RequestSchema.shape}).strict(),isJSONRPCRequest=value=>JSONRPCRequestSchema.safeParse(value).success,JSONRPCNotificationSchema=object2({jsonrpc:literal(JSONRPC_VERSION),...NotificationSchema.shape}).strict(),isJSONRPCNotification=value=>JSONRPCNotificationSchema.safeParse(value).success,JSONRPCResultResponseSchema=object2({jsonrpc:literal(JSONRPC_VERSION),id:RequestIdSchema,result:ResultSchema}).strict(),isJSONRPCResultResponse=value=>JSONRPCResultResponseSchema.safeParse(value).success;var ErrorCode;(function(ErrorCode2){ErrorCode2[ErrorCode2.ConnectionClosed=-32e3]="ConnectionClosed",ErrorCode2[ErrorCode2.RequestTimeout=-32001]="RequestTimeout",ErrorCode2[ErrorCode2.ParseError=-32700]="ParseError",ErrorCode2[ErrorCode2.InvalidRequest=-32600]="InvalidRequest",ErrorCode2[ErrorCode2.MethodNotFound=-32601]="MethodNotFound",ErrorCode2[ErrorCode2.InvalidParams=-32602]="InvalidParams",ErrorCode2[ErrorCode2.InternalError=-32603]="InternalError",ErrorCode2[ErrorCode2.UrlElicitationRequired=-32042]="UrlElicitationRequired"})(ErrorCode||(ErrorCode={}));var JSONRPCErrorResponseSchema=object2({jsonrpc:literal(JSONRPC_VERSION),id:RequestIdSchema.optional(),error:object2({code:number2().int(),message:string2(),data:unknown().optional()})}).strict();var isJSONRPCErrorResponse=value=>JSONRPCErrorResponseSchema.safeParse(value).success;var JSONRPCMessageSchema=union([JSONRPCRequestSchema,JSONRPCNotificationSchema,JSONRPCResultResponseSchema,JSONRPCErrorResponseSchema]),JSONRPCResponseSchema=union([JSONRPCResultResponseSchema,JSONRPCErrorResponseSchema]),EmptyResultSchema=ResultSchema.strict(),CancelledNotificationParamsSchema=NotificationsParamsSchema.extend({requestId:RequestIdSchema.optional(),reason:string2().optional()}),CancelledNotificationSchema=NotificationSchema.extend({method:literal("notifications/cancelled"),params:CancelledNotificationParamsSchema}),IconSchema=object2({src:string2(),mimeType:string2().optional(),sizes:array(string2()).optional(),theme:_enum(["light","dark"]).optional()}),IconsSchema=object2({icons:array(IconSchema).optional()}),BaseMetadataSchema=object2({name:string2(),title:string2().optional()}),ImplementationSchema=BaseMetadataSchema.extend({...BaseMetadataSchema.shape,...IconsSchema.shape,version:string2(),websiteUrl:string2().optional(),description:string2().optional()}),FormElicitationCapabilitySchema=intersection(object2({applyDefaults:boolean2().optional()}),record(string2(),unknown())),ElicitationCapabilitySchema=preprocess(value=>value&&typeof value=="object"&&!Array.isArray(value)&&Object.keys(value).length===0?{form:{}}:value,intersection(object2({form:FormElicitationCapabilitySchema.optional(),url:AssertObjectSchema.optional()}),record(string2(),unknown()).optional())),ClientTasksCapabilitySchema=looseObject({list:AssertObjectSchema.optional(),cancel:AssertObjectSchema.optional(),requests:looseObject({sampling:looseObject({createMessage:AssertObjectSchema.optional()}).optional(),elicitation:looseObject({create:AssertObjectSchema.optional()}).optional()}).optional()}),ServerTasksCapabilitySchema=looseObject({list:AssertObjectSchema.optional(),cancel:AssertObjectSchema.optional(),requests:looseObject({tools:looseObject({call:AssertObjectSchema.optional()}).optional()}).optional()}),ClientCapabilitiesSchema=object2({experimental:record(string2(),AssertObjectSchema).optional(),sampling:object2({context:AssertObjectSchema.optional(),tools:AssertObjectSchema.optional()}).optional(),elicitation:ElicitationCapabilitySchema.optional(),roots:object2({listChanged:boolean2().optional()}).optional(),tasks:ClientTasksCapabilitySchema.optional()}),InitializeRequestParamsSchema=BaseRequestParamsSchema.extend({protocolVersion:string2(),capabilities:ClientCapabilitiesSchema,clientInfo:ImplementationSchema}),InitializeRequestSchema=RequestSchema.extend({method:literal("initialize"),params:InitializeRequestParamsSchema});var ServerCapabilitiesSchema=object2({experimental:record(string2(),AssertObjectSchema).optional(),logging:AssertObjectSchema.optional(),completions:AssertObjectSchema.optional(),prompts:object2({listChanged:boolean2().optional()}).optional(),resources:object2({subscribe:boolean2().optional(),listChanged:boolean2().optional()}).optional(),tools:object2({listChanged:boolean2().optional()}).optional(),tasks:ServerTasksCapabilitySchema.optional()}),InitializeResultSchema=ResultSchema.extend({protocolVersion:string2(),capabilities:ServerCapabilitiesSchema,serverInfo:ImplementationSchema,instructions:string2().optional()}),InitializedNotificationSchema=NotificationSchema.extend({method:literal("notifications/initialized"),params:NotificationsParamsSchema.optional()});var PingRequestSchema=RequestSchema.extend({method:literal("ping"),params:BaseRequestParamsSchema.optional()}),ProgressSchema=object2({progress:number2(),total:optional(number2()),message:optional(string2())}),ProgressNotificationParamsSchema=object2({...NotificationsParamsSchema.shape,...ProgressSchema.shape,progressToken:ProgressTokenSchema}),ProgressNotificationSchema=NotificationSchema.extend({method:literal("notifications/progress"),params:ProgressNotificationParamsSchema}),PaginatedRequestParamsSchema=BaseRequestParamsSchema.extend({cursor:CursorSchema.optional()}),PaginatedRequestSchema=RequestSchema.extend({params:PaginatedRequestParamsSchema.optional()}),PaginatedResultSchema=ResultSchema.extend({nextCursor:CursorSchema.optional()}),TaskStatusSchema=_enum(["working","input_required","completed","failed","cancelled"]),TaskSchema=object2({taskId:string2(),status:TaskStatusSchema,ttl:union([number2(),_null3()]),createdAt:string2(),lastUpdatedAt:string2(),pollInterval:optional(number2()),statusMessage:optional(string2())}),CreateTaskResultSchema=ResultSchema.extend({task:TaskSchema}),TaskStatusNotificationParamsSchema=NotificationsParamsSchema.merge(TaskSchema),TaskStatusNotificationSchema=NotificationSchema.extend({method:literal("notifications/tasks/status"),params:TaskStatusNotificationParamsSchema}),GetTaskRequestSchema=RequestSchema.extend({method:literal("tasks/get"),params:BaseRequestParamsSchema.extend({taskId:string2()})}),GetTaskResultSchema=ResultSchema.merge(TaskSchema),GetTaskPayloadRequestSchema=RequestSchema.extend({method:literal("tasks/result"),params:BaseRequestParamsSchema.extend({taskId:string2()})}),GetTaskPayloadResultSchema=ResultSchema.loose(),ListTasksRequestSchema=PaginatedRequestSchema.extend({method:literal("tasks/list")}),ListTasksResultSchema=PaginatedResultSchema.extend({tasks:array(TaskSchema)}),CancelTaskRequestSchema=RequestSchema.extend({method:literal("tasks/cancel"),params:BaseRequestParamsSchema.extend({taskId:string2()})}),CancelTaskResultSchema=ResultSchema.merge(TaskSchema),ResourceContentsSchema=object2({uri:string2(),mimeType:optional(string2()),_meta:record(string2(),unknown()).optional()}),TextResourceContentsSchema=ResourceContentsSchema.extend({text:string2()}),Base64Schema=string2().refine(val=>{try{return atob(val),!0}catch{return!1}},{message:"Invalid Base64 string"}),BlobResourceContentsSchema=ResourceContentsSchema.extend({blob:Base64Schema}),RoleSchema=_enum(["user","assistant"]),AnnotationsSchema=object2({audience:array(RoleSchema).optional(),priority:number2().min(0).max(1).optional(),lastModified:iso_exports2.datetime({offset:!0}).optional()}),ResourceSchema=object2({...BaseMetadataSchema.shape,...IconsSchema.shape,uri:string2(),description:optional(string2()),mimeType:optional(string2()),annotations:AnnotationsSchema.optional(),_meta:optional(looseObject({}))}),ResourceTemplateSchema=object2({...BaseMetadataSchema.shape,...IconsSchema.shape,uriTemplate:string2(),description:optional(string2()),mimeType:optional(string2()),annotations:AnnotationsSchema.optional(),_meta:optional(looseObject({}))}),ListResourcesRequestSchema=PaginatedRequestSchema.extend({method:literal("resources/list")}),ListResourcesResultSchema=PaginatedResultSchema.extend({resources:array(ResourceSchema)}),ListResourceTemplatesRequestSchema=PaginatedRequestSchema.extend({method:literal("resources/templates/list")}),ListResourceTemplatesResultSchema=PaginatedResultSchema.extend({resourceTemplates:array(ResourceTemplateSchema)}),ResourceRequestParamsSchema=BaseRequestParamsSchema.extend({uri:string2()}),ReadResourceRequestParamsSchema=ResourceRequestParamsSchema,ReadResourceRequestSchema=RequestSchema.extend({method:literal("resources/read"),params:ReadResourceRequestParamsSchema}),ReadResourceResultSchema=ResultSchema.extend({contents:array(union([TextResourceContentsSchema,BlobResourceContentsSchema]))}),ResourceListChangedNotificationSchema=NotificationSchema.extend({method:literal("notifications/resources/list_changed"),params:NotificationsParamsSchema.optional()}),SubscribeRequestParamsSchema=ResourceRequestParamsSchema,SubscribeRequestSchema=RequestSchema.extend({method:literal("resources/subscribe"),params:SubscribeRequestParamsSchema}),UnsubscribeRequestParamsSchema=ResourceRequestParamsSchema,UnsubscribeRequestSchema=RequestSchema.extend({method:literal("resources/unsubscribe"),params:UnsubscribeRequestParamsSchema}),ResourceUpdatedNotificationParamsSchema=NotificationsParamsSchema.extend({uri:string2()}),ResourceUpdatedNotificationSchema=NotificationSchema.extend({method:literal("notifications/resources/updated"),params:ResourceUpdatedNotificationParamsSchema}),PromptArgumentSchema=object2({name:string2(),description:optional(string2()),required:optional(boolean2())}),PromptSchema=object2({...BaseMetadataSchema.shape,...IconsSchema.shape,description:optional(string2()),arguments:optional(array(PromptArgumentSchema)),_meta:optional(looseObject({}))}),ListPromptsRequestSchema=PaginatedRequestSchema.extend({method:literal("prompts/list")}),ListPromptsResultSchema=PaginatedResultSchema.extend({prompts:array(PromptSchema)}),GetPromptRequestParamsSchema=BaseRequestParamsSchema.extend({name:string2(),arguments:record(string2(),string2()).optional()}),GetPromptRequestSchema=RequestSchema.extend({method:literal("prompts/get"),params:GetPromptRequestParamsSchema}),TextContentSchema=object2({type:literal("text"),text:string2(),annotations:AnnotationsSchema.optional(),_meta:record(string2(),unknown()).optional()}),ImageContentSchema=object2({type:literal("image"),data:Base64Schema,mimeType:string2(),annotations:AnnotationsSchema.optional(),_meta:record(string2(),unknown()).optional()}),AudioContentSchema=object2({type:literal("audio"),data:Base64Schema,mimeType:string2(),annotations:AnnotationsSchema.optional(),_meta:record(string2(),unknown()).optional()}),ToolUseContentSchema=object2({type:literal("tool_use"),name:string2(),id:string2(),input:record(string2(),unknown()),_meta:record(string2(),unknown()).optional()}),EmbeddedResourceSchema=object2({type:literal("resource"),resource:union([TextResourceContentsSchema,BlobResourceContentsSchema]),annotations:AnnotationsSchema.optional(),_meta:record(string2(),unknown()).optional()}),ResourceLinkSchema=ResourceSchema.extend({type:literal("resource_link")}),ContentBlockSchema=union([TextContentSchema,ImageContentSchema,AudioContentSchema,ResourceLinkSchema,EmbeddedResourceSchema]),PromptMessageSchema=object2({role:RoleSchema,content:ContentBlockSchema}),GetPromptResultSchema=ResultSchema.extend({description:string2().optional(),messages:array(PromptMessageSchema)}),PromptListChangedNotificationSchema=NotificationSchema.extend({method:literal("notifications/prompts/list_changed"),params:NotificationsParamsSchema.optional()}),ToolAnnotationsSchema=object2({title:string2().optional(),readOnlyHint:boolean2().optional(),destructiveHint:boolean2().optional(),idempotentHint:boolean2().optional(),openWorldHint:boolean2().optional()}),ToolExecutionSchema=object2({taskSupport:_enum(["required","optional","forbidden"]).optional()}),ToolSchema=object2({...BaseMetadataSchema.shape,...IconsSchema.shape,description:string2().optional(),inputSchema:object2({type:literal("object"),properties:record(string2(),AssertObjectSchema).optional(),required:array(string2()).optional()}).catchall(unknown()),outputSchema:object2({type:literal("object"),properties:record(string2(),AssertObjectSchema).optional(),required:array(string2()).optional()}).catchall(unknown()).optional(),annotations:ToolAnnotationsSchema.optional(),execution:ToolExecutionSchema.optional(),_meta:record(string2(),unknown()).optional()}),ListToolsRequestSchema=PaginatedRequestSchema.extend({method:literal("tools/list")}),ListToolsResultSchema=PaginatedResultSchema.extend({tools:array(ToolSchema)}),CallToolResultSchema=ResultSchema.extend({content:array(ContentBlockSchema).default([]),structuredContent:record(string2(),unknown()).optional(),isError:boolean2().optional()}),CompatibilityCallToolResultSchema=CallToolResultSchema.or(ResultSchema.extend({toolResult:unknown()})),CallToolRequestParamsSchema=TaskAugmentedRequestParamsSchema.extend({name:string2(),arguments:record(string2(),unknown()).optional()}),CallToolRequestSchema=RequestSchema.extend({method:literal("tools/call"),params:CallToolRequestParamsSchema}),ToolListChangedNotificationSchema=NotificationSchema.extend({method:literal("notifications/tools/list_changed"),params:NotificationsParamsSchema.optional()}),ListChangedOptionsBaseSchema=object2({autoRefresh:boolean2().default(!0),debounceMs:number2().int().nonnegative().default(300)}),LoggingLevelSchema=_enum(["debug","info","notice","warning","error","critical","alert","emergency"]),SetLevelRequestParamsSchema=BaseRequestParamsSchema.extend({level:LoggingLevelSchema}),SetLevelRequestSchema=RequestSchema.extend({method:literal("logging/setLevel"),params:SetLevelRequestParamsSchema}),LoggingMessageNotificationParamsSchema=NotificationsParamsSchema.extend({level:LoggingLevelSchema,logger:string2().optional(),data:unknown()}),LoggingMessageNotificationSchema=NotificationSchema.extend({method:literal("notifications/message"),params:LoggingMessageNotificationParamsSchema}),ModelHintSchema=object2({name:string2().optional()}),ModelPreferencesSchema=object2({hints:array(ModelHintSchema).optional(),costPriority:number2().min(0).max(1).optional(),speedPriority:number2().min(0).max(1).optional(),intelligencePriority:number2().min(0).max(1).optional()}),ToolChoiceSchema=object2({mode:_enum(["auto","required","none"]).optional()}),ToolResultContentSchema=object2({type:literal("tool_result"),toolUseId:string2().describe("The unique identifier for the corresponding tool call."),content:array(ContentBlockSchema).default([]),structuredContent:object2({}).loose().optional(),isError:boolean2().optional(),_meta:record(string2(),unknown()).optional()}),SamplingContentSchema=discriminatedUnion("type",[TextContentSchema,ImageContentSchema,AudioContentSchema]),SamplingMessageContentBlockSchema=discriminatedUnion("type",[TextContentSchema,ImageContentSchema,AudioContentSchema,ToolUseContentSchema,ToolResultContentSchema]),SamplingMessageSchema=object2({role:RoleSchema,content:union([SamplingMessageContentBlockSchema,array(SamplingMessageContentBlockSchema)]),_meta:record(string2(),unknown()).optional()}),CreateMessageRequestParamsSchema=TaskAugmentedRequestParamsSchema.extend({messages:array(SamplingMessageSchema),modelPreferences:ModelPreferencesSchema.optional(),systemPrompt:string2().optional(),includeContext:_enum(["none","thisServer","allServers"]).optional(),temperature:number2().optional(),maxTokens:number2().int(),stopSequences:array(string2()).optional(),metadata:AssertObjectSchema.optional(),tools:array(ToolSchema).optional(),toolChoice:ToolChoiceSchema.optional()}),CreateMessageRequestSchema=RequestSchema.extend({method:literal("sampling/createMessage"),params:CreateMessageRequestParamsSchema}),CreateMessageResultSchema=ResultSchema.extend({model:string2(),stopReason:optional(_enum(["endTurn","stopSequence","maxTokens"]).or(string2())),role:RoleSchema,content:SamplingContentSchema}),CreateMessageResultWithToolsSchema=ResultSchema.extend({model:string2(),stopReason:optional(_enum(["endTurn","stopSequence","maxTokens","toolUse"]).or(string2())),role:RoleSchema,content:union([SamplingMessageContentBlockSchema,array(SamplingMessageContentBlockSchema)])}),BooleanSchemaSchema=object2({type:literal("boolean"),title:string2().optional(),description:string2().optional(),default:boolean2().optional()}),StringSchemaSchema=object2({type:literal("string"),title:string2().optional(),description:string2().optional(),minLength:number2().optional(),maxLength:number2().optional(),format:_enum(["email","uri","date","date-time"]).optional(),default:string2().optional()}),NumberSchemaSchema=object2({type:_enum(["number","integer"]),title:string2().optional(),description:string2().optional(),minimum:number2().optional(),maximum:number2().optional(),default:number2().optional()}),UntitledSingleSelectEnumSchemaSchema=object2({type:literal("string"),title:string2().optional(),description:string2().optional(),enum:array(string2()),default:string2().optional()}),TitledSingleSelectEnumSchemaSchema=object2({type:literal("string"),title:string2().optional(),description:string2().optional(),oneOf:array(object2({const:string2(),title:string2()})),default:string2().optional()}),LegacyTitledEnumSchemaSchema=object2({type:literal("string"),title:string2().optional(),description:string2().optional(),enum:array(string2()),enumNames:array(string2()).optional(),default:string2().optional()}),SingleSelectEnumSchemaSchema=union([UntitledSingleSelectEnumSchemaSchema,TitledSingleSelectEnumSchemaSchema]),UntitledMultiSelectEnumSchemaSchema=object2({type:literal("array"),title:string2().optional(),description:string2().optional(),minItems:number2().optional(),maxItems:number2().optional(),items:object2({type:literal("string"),enum:array(string2())}),default:array(string2()).optional()}),TitledMultiSelectEnumSchemaSchema=object2({type:literal("array"),title:string2().optional(),description:string2().optional(),minItems:number2().optional(),maxItems:number2().optional(),items:object2({anyOf:array(object2({const:string2(),title:string2()}))}),default:array(string2()).optional()}),MultiSelectEnumSchemaSchema=union([UntitledMultiSelectEnumSchemaSchema,TitledMultiSelectEnumSchemaSchema]),EnumSchemaSchema=union([LegacyTitledEnumSchemaSchema,SingleSelectEnumSchemaSchema,MultiSelectEnumSchemaSchema]),PrimitiveSchemaDefinitionSchema=union([EnumSchemaSchema,BooleanSchemaSchema,StringSchemaSchema,NumberSchemaSchema]),ElicitRequestFormParamsSchema=TaskAugmentedRequestParamsSchema.extend({mode:literal("form").optional(),message:string2(),requestedSchema:object2({type:literal("object"),properties:record(string2(),PrimitiveSchemaDefinitionSchema),required:array(string2()).optional()})}),ElicitRequestURLParamsSchema=TaskAugmentedRequestParamsSchema.extend({mode:literal("url"),message:string2(),elicitationId:string2(),url:string2().url()}),ElicitRequestParamsSchema=union([ElicitRequestFormParamsSchema,ElicitRequestURLParamsSchema]),ElicitRequestSchema=RequestSchema.extend({method:literal("elicitation/create"),params:ElicitRequestParamsSchema}),ElicitationCompleteNotificationParamsSchema=NotificationsParamsSchema.extend({elicitationId:string2()}),ElicitationCompleteNotificationSchema=NotificationSchema.extend({method:literal("notifications/elicitation/complete"),params:ElicitationCompleteNotificationParamsSchema}),ElicitResultSchema=ResultSchema.extend({action:_enum(["accept","decline","cancel"]),content:preprocess(val=>val===null?void 0:val,record(string2(),union([string2(),number2(),boolean2(),array(string2())])).optional())}),ResourceTemplateReferenceSchema=object2({type:literal("ref/resource"),uri:string2()});var PromptReferenceSchema=object2({type:literal("ref/prompt"),name:string2()}),CompleteRequestParamsSchema=BaseRequestParamsSchema.extend({ref:union([PromptReferenceSchema,ResourceTemplateReferenceSchema]),argument:object2({name:string2(),value:string2()}),context:object2({arguments:record(string2(),string2()).optional()}).optional()}),CompleteRequestSchema=RequestSchema.extend({method:literal("completion/complete"),params:CompleteRequestParamsSchema});var CompleteResultSchema=ResultSchema.extend({completion:looseObject({values:array(string2()).max(100),total:optional(number2().int()),hasMore:optional(boolean2())})}),RootSchema=object2({uri:string2().startsWith("file://"),name:string2().optional(),_meta:record(string2(),unknown()).optional()}),ListRootsRequestSchema=RequestSchema.extend({method:literal("roots/list"),params:BaseRequestParamsSchema.optional()}),ListRootsResultSchema=ResultSchema.extend({roots:array(RootSchema)}),RootsListChangedNotificationSchema=NotificationSchema.extend({method:literal("notifications/roots/list_changed"),params:NotificationsParamsSchema.optional()}),ClientRequestSchema=union([PingRequestSchema,InitializeRequestSchema,CompleteRequestSchema,SetLevelRequestSchema,GetPromptRequestSchema,ListPromptsRequestSchema,ListResourcesRequestSchema,ListResourceTemplatesRequestSchema,ReadResourceRequestSchema,SubscribeRequestSchema,UnsubscribeRequestSchema,CallToolRequestSchema,ListToolsRequestSchema,GetTaskRequestSchema,GetTaskPayloadRequestSchema,ListTasksRequestSchema,CancelTaskRequestSchema]),ClientNotificationSchema=union([CancelledNotificationSchema,ProgressNotificationSchema,InitializedNotificationSchema,RootsListChangedNotificationSchema,TaskStatusNotificationSchema]),ClientResultSchema=union([EmptyResultSchema,CreateMessageResultSchema,CreateMessageResultWithToolsSchema,ElicitResultSchema,ListRootsResultSchema,GetTaskResultSchema,ListTasksResultSchema,CreateTaskResultSchema]),ServerRequestSchema=union([PingRequestSchema,CreateMessageRequestSchema,ElicitRequestSchema,ListRootsRequestSchema,GetTaskRequestSchema,GetTaskPayloadRequestSchema,ListTasksRequestSchema,CancelTaskRequestSchema]),ServerNotificationSchema=union([CancelledNotificationSchema,ProgressNotificationSchema,LoggingMessageNotificationSchema,ResourceUpdatedNotificationSchema,ResourceListChangedNotificationSchema,ToolListChangedNotificationSchema,PromptListChangedNotificationSchema,TaskStatusNotificationSchema,ElicitationCompleteNotificationSchema]),ServerResultSchema=union([EmptyResultSchema,InitializeResultSchema,CompleteResultSchema,GetPromptResultSchema,ListPromptsResultSchema,ListResourcesResultSchema,ListResourceTemplatesResultSchema,ReadResourceResultSchema,CallToolResultSchema,ListToolsResultSchema,GetTaskResultSchema,ListTasksResultSchema,CreateTaskResultSchema]),McpError=class _McpError extends Error{constructor(code,message,data){super(`MCP error ${code}: ${message}`),this.code=code,this.data=data,this.name="McpError"}static fromError(code,message,data){if(code===ErrorCode.UrlElicitationRequired&&data){let errorData=data;if(errorData.elicitations)return new UrlElicitationRequiredError(errorData.elicitations,message)}return new _McpError(code,message,data)}},UrlElicitationRequiredError=class extends McpError{constructor(elicitations,message=`URL elicitation${elicitations.length>1?"s":""} required`){super(ErrorCode.UrlElicitationRequired,message,{elicitations})}get elicitations(){return this.data?.elicitations??[]}};function isTerminal(status){return status==="completed"||status==="failed"||status==="cancelled"}var ignoreOverride=Symbol("Let zodToJsonSchema decide on which parser to use");var ALPHA_NUMERIC=new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");function getMethodLiteral(schema){let methodSchema=getObjectShape(schema)?.method;if(!methodSchema)throw new Error("Schema is missing a method literal");let value=getLiteralValue(methodSchema);if(typeof value!="string")throw new Error("Schema method literal must be a string");return value}function parseWithCompat(schema,data){let result=safeParse2(schema,data);if(!result.success)throw result.error;return result.data}var DEFAULT_REQUEST_TIMEOUT_MSEC=6e4,Protocol=class{constructor(_options){this._options=_options,this._requestMessageId=0,this._requestHandlers=new Map,this._requestHandlerAbortControllers=new Map,this._notificationHandlers=new Map,this._responseHandlers=new Map,this._progressHandlers=new Map,this._timeoutInfo=new Map,this._pendingDebouncedNotifications=new Set,this._taskProgressTokens=new Map,this._requestResolvers=new Map,this.setNotificationHandler(CancelledNotificationSchema,notification=>{this._oncancel(notification)}),this.setNotificationHandler(ProgressNotificationSchema,notification=>{this._onprogress(notification)}),this.setRequestHandler(PingRequestSchema,_request=>({})),this._taskStore=_options?.taskStore,this._taskMessageQueue=_options?.taskMessageQueue,this._taskStore&&(this.setRequestHandler(GetTaskRequestSchema,async(request,extra)=>{let task=await this._taskStore.getTask(request.params.taskId,extra.sessionId);if(!task)throw new McpError(ErrorCode.InvalidParams,"Failed to retrieve task: Task not found");return{...task}}),this.setRequestHandler(GetTaskPayloadRequestSchema,async(request,extra)=>{let handleTaskResult=async()=>{let taskId=request.params.taskId;if(this._taskMessageQueue){let queuedMessage;for(;queuedMessage=await this._taskMessageQueue.dequeue(taskId,extra.sessionId);){if(queuedMessage.type==="response"||queuedMessage.type==="error"){let message=queuedMessage.message,requestId=message.id,resolver=this._requestResolvers.get(requestId);if(resolver)if(this._requestResolvers.delete(requestId),queuedMessage.type==="response")resolver(message);else{let errorMessage=message,error2=new McpError(errorMessage.error.code,errorMessage.error.message,errorMessage.error.data);resolver(error2)}else{let messageType=queuedMessage.type==="response"?"Response":"Error";this._onerror(new Error(`${messageType} handler missing for request ${requestId}`))}continue}await this._transport?.send(queuedMessage.message,{relatedRequestId:extra.requestId})}}let task=await this._taskStore.getTask(taskId,extra.sessionId);if(!task)throw new McpError(ErrorCode.InvalidParams,`Task not found: ${taskId}`);if(!isTerminal(task.status))return await this._waitForTaskUpdate(taskId,extra.signal),await handleTaskResult();if(isTerminal(task.status)){let result=await this._taskStore.getTaskResult(taskId,extra.sessionId);return this._clearTaskQueue(taskId),{...result,_meta:{...result._meta,[RELATED_TASK_META_KEY]:{taskId}}}}return await handleTaskResult()};return await handleTaskResult()}),this.setRequestHandler(ListTasksRequestSchema,async(request,extra)=>{try{let{tasks,nextCursor}=await this._taskStore.listTasks(request.params?.cursor,extra.sessionId);return{tasks,nextCursor,_meta:{}}}catch(error2){throw new McpError(ErrorCode.InvalidParams,`Failed to list tasks: ${error2 instanceof Error?error2.message:String(error2)}`)}}),this.setRequestHandler(CancelTaskRequestSchema,async(request,extra)=>{try{let task=await this._taskStore.getTask(request.params.taskId,extra.sessionId);if(!task)throw new McpError(ErrorCode.InvalidParams,`Task not found: ${request.params.taskId}`);if(isTerminal(task.status))throw new McpError(ErrorCode.InvalidParams,`Cannot cancel task in terminal status: ${task.status}`);await this._taskStore.updateTaskStatus(request.params.taskId,"cancelled","Client cancelled task execution.",extra.sessionId),this._clearTaskQueue(request.params.taskId);let cancelledTask=await this._taskStore.getTask(request.params.taskId,extra.sessionId);if(!cancelledTask)throw new McpError(ErrorCode.InvalidParams,`Task not found after cancellation: ${request.params.taskId}`);return{_meta:{},...cancelledTask}}catch(error2){throw error2 instanceof McpError?error2:new McpError(ErrorCode.InvalidRequest,`Failed to cancel task: ${error2 instanceof Error?error2.message:String(error2)}`)}}))}async _oncancel(notification){if(!notification.params.requestId)return;this._requestHandlerAbortControllers.get(notification.params.requestId)?.abort(notification.params.reason)}_setupTimeout(messageId,timeout,maxTotalTimeout,onTimeout,resetTimeoutOnProgress=!1){this._timeoutInfo.set(messageId,{timeoutId:setTimeout(onTimeout,timeout),startTime:Date.now(),timeout,maxTotalTimeout,resetTimeoutOnProgress,onTimeout})}_resetTimeout(messageId){let info=this._timeoutInfo.get(messageId);if(!info)return!1;let totalElapsed=Date.now()-info.startTime;if(info.maxTotalTimeout&&totalElapsed>=info.maxTotalTimeout)throw this._timeoutInfo.delete(messageId),McpError.fromError(ErrorCode.RequestTimeout,"Maximum total timeout exceeded",{maxTotalTimeout:info.maxTotalTimeout,totalElapsed});return clearTimeout(info.timeoutId),info.timeoutId=setTimeout(info.onTimeout,info.timeout),!0}_cleanupTimeout(messageId){let info=this._timeoutInfo.get(messageId);info&&(clearTimeout(info.timeoutId),this._timeoutInfo.delete(messageId))}async connect(transport){if(this._transport)throw new Error("Already connected to a transport. Call close() before connecting to a new transport, or use a separate Protocol instance per connection.");this._transport=transport;let _onclose=this.transport?.onclose;this._transport.onclose=()=>{_onclose?.(),this._onclose()};let _onerror=this.transport?.onerror;this._transport.onerror=error2=>{_onerror?.(error2),this._onerror(error2)};let _onmessage=this._transport?.onmessage;this._transport.onmessage=(message,extra)=>{_onmessage?.(message,extra),isJSONRPCResultResponse(message)||isJSONRPCErrorResponse(message)?this._onresponse(message):isJSONRPCRequest(message)?this._onrequest(message,extra):isJSONRPCNotification(message)?this._onnotification(message):this._onerror(new Error(`Unknown message type: ${JSON.stringify(message)}`))},await this._transport.start()}_onclose(){let responseHandlers=this._responseHandlers;this._responseHandlers=new Map,this._progressHandlers.clear(),this._taskProgressTokens.clear(),this._pendingDebouncedNotifications.clear();for(let controller of this._requestHandlerAbortControllers.values())controller.abort();this._requestHandlerAbortControllers.clear();let error2=McpError.fromError(ErrorCode.ConnectionClosed,"Connection closed");this._transport=void 0,this.onclose?.();for(let handler of responseHandlers.values())handler(error2)}_onerror(error2){this.onerror?.(error2)}_onnotification(notification){let handler=this._notificationHandlers.get(notification.method)??this.fallbackNotificationHandler;handler!==void 0&&Promise.resolve().then(()=>handler(notification)).catch(error2=>this._onerror(new Error(`Uncaught error in notification handler: ${error2}`)))}_onrequest(request,extra){let handler=this._requestHandlers.get(request.method)??this.fallbackRequestHandler,capturedTransport=this._transport,relatedTaskId=request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;if(handler===void 0){let errorResponse={jsonrpc:"2.0",id:request.id,error:{code:ErrorCode.MethodNotFound,message:"Method not found"}};relatedTaskId&&this._taskMessageQueue?this._enqueueTaskMessage(relatedTaskId,{type:"error",message:errorResponse,timestamp:Date.now()},capturedTransport?.sessionId).catch(error2=>this._onerror(new Error(`Failed to enqueue error response: ${error2}`))):capturedTransport?.send(errorResponse).catch(error2=>this._onerror(new Error(`Failed to send an error response: ${error2}`)));return}let abortController=new AbortController;this._requestHandlerAbortControllers.set(request.id,abortController);let taskCreationParams=isTaskAugmentedRequestParams(request.params)?request.params.task:void 0,taskStore=this._taskStore?this.requestTaskStore(request,capturedTransport?.sessionId):void 0,fullExtra={signal:abortController.signal,sessionId:capturedTransport?.sessionId,_meta:request.params?._meta,sendNotification:async notification=>{if(abortController.signal.aborted)return;let notificationOptions={relatedRequestId:request.id};relatedTaskId&&(notificationOptions.relatedTask={taskId:relatedTaskId}),await this.notification(notification,notificationOptions)},sendRequest:async(r,resultSchema,options)=>{if(abortController.signal.aborted)throw new McpError(ErrorCode.ConnectionClosed,"Request was cancelled");let requestOptions={...options,relatedRequestId:request.id};relatedTaskId&&!requestOptions.relatedTask&&(requestOptions.relatedTask={taskId:relatedTaskId});let effectiveTaskId=requestOptions.relatedTask?.taskId??relatedTaskId;return effectiveTaskId&&taskStore&&await taskStore.updateTaskStatus(effectiveTaskId,"input_required"),await this.request(r,resultSchema,requestOptions)},authInfo:extra?.authInfo,requestId:request.id,requestInfo:extra?.requestInfo,taskId:relatedTaskId,taskStore,taskRequestedTtl:taskCreationParams?.ttl,closeSSEStream:extra?.closeSSEStream,closeStandaloneSSEStream:extra?.closeStandaloneSSEStream};Promise.resolve().then(()=>{taskCreationParams&&this.assertTaskHandlerCapability(request.method)}).then(()=>handler(request,fullExtra)).then(async result=>{if(abortController.signal.aborted)return;let response={result,jsonrpc:"2.0",id:request.id};relatedTaskId&&this._taskMessageQueue?await this._enqueueTaskMessage(relatedTaskId,{type:"response",message:response,timestamp:Date.now()},capturedTransport?.sessionId):await capturedTransport?.send(response)},async error2=>{if(abortController.signal.aborted)return;let errorResponse={jsonrpc:"2.0",id:request.id,error:{code:Number.isSafeInteger(error2.code)?error2.code:ErrorCode.InternalError,message:error2.message??"Internal error",...error2.data!==void 0&&{data:error2.data}}};relatedTaskId&&this._taskMessageQueue?await this._enqueueTaskMessage(relatedTaskId,{type:"error",message:errorResponse,timestamp:Date.now()},capturedTransport?.sessionId):await capturedTransport?.send(errorResponse)}).catch(error2=>this._onerror(new Error(`Failed to send response: ${error2}`))).finally(()=>{this._requestHandlerAbortControllers.delete(request.id)})}_onprogress(notification){let{progressToken,...params}=notification.params,messageId=Number(progressToken),handler=this._progressHandlers.get(messageId);if(!handler){this._onerror(new Error(`Received a progress notification for an unknown token: ${JSON.stringify(notification)}`));return}let responseHandler=this._responseHandlers.get(messageId),timeoutInfo=this._timeoutInfo.get(messageId);if(timeoutInfo&&responseHandler&&timeoutInfo.resetTimeoutOnProgress)try{this._resetTimeout(messageId)}catch(error2){this._responseHandlers.delete(messageId),this._progressHandlers.delete(messageId),this._cleanupTimeout(messageId),responseHandler(error2);return}handler(params)}_onresponse(response){let messageId=Number(response.id),resolver=this._requestResolvers.get(messageId);if(resolver){if(this._requestResolvers.delete(messageId),isJSONRPCResultResponse(response))resolver(response);else{let error2=new McpError(response.error.code,response.error.message,response.error.data);resolver(error2)}return}let handler=this._responseHandlers.get(messageId);if(handler===void 0){this._onerror(new Error(`Received a response for an unknown message ID: ${JSON.stringify(response)}`));return}this._responseHandlers.delete(messageId),this._cleanupTimeout(messageId);let isTaskResponse=!1;if(isJSONRPCResultResponse(response)&&response.result&&typeof response.result=="object"){let result=response.result;if(result.task&&typeof result.task=="object"){let task=result.task;typeof task.taskId=="string"&&(isTaskResponse=!0,this._taskProgressTokens.set(task.taskId,messageId))}}if(isTaskResponse||this._progressHandlers.delete(messageId),isJSONRPCResultResponse(response))handler(response);else{let error2=McpError.fromError(response.error.code,response.error.message,response.error.data);handler(error2)}}get transport(){return this._transport}async close(){await this._transport?.close()}async*requestStream(request,resultSchema,options){let{task}=options??{};if(!task){try{yield{type:"result",result:await this.request(request,resultSchema,options)}}catch(error2){yield{type:"error",error:error2 instanceof McpError?error2:new McpError(ErrorCode.InternalError,String(error2))}}return}let taskId;try{let createResult=await this.request(request,CreateTaskResultSchema,options);if(createResult.task)taskId=createResult.task.taskId,yield{type:"taskCreated",task:createResult.task};else throw new McpError(ErrorCode.InternalError,"Task creation did not return a task");for(;;){let task2=await this.getTask({taskId},options);if(yield{type:"taskStatus",task:task2},isTerminal(task2.status)){task2.status==="completed"?yield{type:"result",result:await this.getTaskResult({taskId},resultSchema,options)}:task2.status==="failed"?yield{type:"error",error:new McpError(ErrorCode.InternalError,`Task ${taskId} failed`)}:task2.status==="cancelled"&&(yield{type:"error",error:new McpError(ErrorCode.InternalError,`Task ${taskId} was cancelled`)});return}if(task2.status==="input_required"){yield{type:"result",result:await this.getTaskResult({taskId},resultSchema,options)};return}let pollInterval=task2.pollInterval??this._options?.defaultTaskPollInterval??1e3;await new Promise(resolve=>setTimeout(resolve,pollInterval)),options?.signal?.throwIfAborted()}}catch(error2){yield{type:"error",error:error2 instanceof McpError?error2:new McpError(ErrorCode.InternalError,String(error2))}}}request(request,resultSchema,options){let{relatedRequestId,resumptionToken,onresumptiontoken,task,relatedTask}=options??{};return new Promise((resolve,reject)=>{let earlyReject=error2=>{reject(error2)};if(!this._transport){earlyReject(new Error("Not connected"));return}if(this._options?.enforceStrictCapabilities===!0)try{this.assertCapabilityForMethod(request.method),task&&this.assertTaskCapability(request.method)}catch(e){earlyReject(e);return}options?.signal?.throwIfAborted();let messageId=this._requestMessageId++,jsonrpcRequest={...request,jsonrpc:"2.0",id:messageId};options?.onprogress&&(this._progressHandlers.set(messageId,options.onprogress),jsonrpcRequest.params={...request.params,_meta:{...request.params?._meta||{},progressToken:messageId}}),task&&(jsonrpcRequest.params={...jsonrpcRequest.params,task}),relatedTask&&(jsonrpcRequest.params={...jsonrpcRequest.params,_meta:{...jsonrpcRequest.params?._meta||{},[RELATED_TASK_META_KEY]:relatedTask}});let cancel=reason=>{this._responseHandlers.delete(messageId),this._progressHandlers.delete(messageId),this._cleanupTimeout(messageId),this._transport?.send({jsonrpc:"2.0",method:"notifications/cancelled",params:{requestId:messageId,reason:String(reason)}},{relatedRequestId,resumptionToken,onresumptiontoken}).catch(error3=>this._onerror(new Error(`Failed to send cancellation: ${error3}`)));let error2=reason instanceof McpError?reason:new McpError(ErrorCode.RequestTimeout,String(reason));reject(error2)};this._responseHandlers.set(messageId,response=>{if(!options?.signal?.aborted){if(response instanceof Error)return reject(response);try{let parseResult=safeParse2(resultSchema,response.result);parseResult.success?resolve(parseResult.data):reject(parseResult.error)}catch(error2){reject(error2)}}}),options?.signal?.addEventListener("abort",()=>{cancel(options?.signal?.reason)});let timeout=options?.timeout??DEFAULT_REQUEST_TIMEOUT_MSEC,timeoutHandler=()=>cancel(McpError.fromError(ErrorCode.RequestTimeout,"Request timed out",{timeout}));this._setupTimeout(messageId,timeout,options?.maxTotalTimeout,timeoutHandler,options?.resetTimeoutOnProgress??!1);let relatedTaskId=relatedTask?.taskId;if(relatedTaskId){let responseResolver=response=>{let handler=this._responseHandlers.get(messageId);handler?handler(response):this._onerror(new Error(`Response handler missing for side-channeled request ${messageId}`))};this._requestResolvers.set(messageId,responseResolver),this._enqueueTaskMessage(relatedTaskId,{type:"request",message:jsonrpcRequest,timestamp:Date.now()}).catch(error2=>{this._cleanupTimeout(messageId),reject(error2)})}else this._transport.send(jsonrpcRequest,{relatedRequestId,resumptionToken,onresumptiontoken}).catch(error2=>{this._cleanupTimeout(messageId),reject(error2)})})}async getTask(params,options){return this.request({method:"tasks/get",params},GetTaskResultSchema,options)}async getTaskResult(params,resultSchema,options){return this.request({method:"tasks/result",params},resultSchema,options)}async listTasks(params,options){return this.request({method:"tasks/list",params},ListTasksResultSchema,options)}async cancelTask(params,options){return this.request({method:"tasks/cancel",params},CancelTaskResultSchema,options)}async notification(notification,options){if(!this._transport)throw new Error("Not connected");this.assertNotificationCapability(notification.method);let relatedTaskId=options?.relatedTask?.taskId;if(relatedTaskId){let jsonrpcNotification2={...notification,jsonrpc:"2.0",params:{...notification.params,_meta:{...notification.params?._meta||{},[RELATED_TASK_META_KEY]:options.relatedTask}}};await this._enqueueTaskMessage(relatedTaskId,{type:"notification",message:jsonrpcNotification2,timestamp:Date.now()});return}if((this._options?.debouncedNotificationMethods??[]).includes(notification.method)&&!notification.params&&!options?.relatedRequestId&&!options?.relatedTask){if(this._pendingDebouncedNotifications.has(notification.method))return;this._pendingDebouncedNotifications.add(notification.method),Promise.resolve().then(()=>{if(this._pendingDebouncedNotifications.delete(notification.method),!this._transport)return;let jsonrpcNotification2={...notification,jsonrpc:"2.0"};options?.relatedTask&&(jsonrpcNotification2={...jsonrpcNotification2,params:{...jsonrpcNotification2.params,_meta:{...jsonrpcNotification2.params?._meta||{},[RELATED_TASK_META_KEY]:options.relatedTask}}}),this._transport?.send(jsonrpcNotification2,options).catch(error2=>this._onerror(error2))});return}let jsonrpcNotification={...notification,jsonrpc:"2.0"};options?.relatedTask&&(jsonrpcNotification={...jsonrpcNotification,params:{...jsonrpcNotification.params,_meta:{...jsonrpcNotification.params?._meta||{},[RELATED_TASK_META_KEY]:options.relatedTask}}}),await this._transport.send(jsonrpcNotification,options)}setRequestHandler(requestSchema,handler){let method=getMethodLiteral(requestSchema);this.assertRequestHandlerCapability(method),this._requestHandlers.set(method,(request,extra)=>{let parsed=parseWithCompat(requestSchema,request);return Promise.resolve(handler(parsed,extra))})}removeRequestHandler(method){this._requestHandlers.delete(method)}assertCanSetRequestHandler(method){if(this._requestHandlers.has(method))throw new Error(`A request handler for ${method} already exists, which would be overridden`)}setNotificationHandler(notificationSchema,handler){let method=getMethodLiteral(notificationSchema);this._notificationHandlers.set(method,notification=>{let parsed=parseWithCompat(notificationSchema,notification);return Promise.resolve(handler(parsed))})}removeNotificationHandler(method){this._notificationHandlers.delete(method)}_cleanupTaskProgressHandler(taskId){let progressToken=this._taskProgressTokens.get(taskId);progressToken!==void 0&&(this._progressHandlers.delete(progressToken),this._taskProgressTokens.delete(taskId))}async _enqueueTaskMessage(taskId,message,sessionId){if(!this._taskStore||!this._taskMessageQueue)throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");let maxQueueSize=this._options?.maxTaskQueueSize;await this._taskMessageQueue.enqueue(taskId,message,sessionId,maxQueueSize)}async _clearTaskQueue(taskId,sessionId){if(this._taskMessageQueue){let messages=await this._taskMessageQueue.dequeueAll(taskId,sessionId);for(let message of messages)if(message.type==="request"&&isJSONRPCRequest(message.message)){let requestId=message.message.id,resolver=this._requestResolvers.get(requestId);resolver?(resolver(new McpError(ErrorCode.InternalError,"Task cancelled or completed")),this._requestResolvers.delete(requestId)):this._onerror(new Error(`Resolver missing for request ${requestId} during task ${taskId} cleanup`))}}}async _waitForTaskUpdate(taskId,signal){let interval=this._options?.defaultTaskPollInterval??1e3;try{let task=await this._taskStore?.getTask(taskId);task?.pollInterval&&(interval=task.pollInterval)}catch{}return new Promise((resolve,reject)=>{if(signal.aborted){reject(new McpError(ErrorCode.InvalidRequest,"Request cancelled"));return}let timeoutId=setTimeout(resolve,interval);signal.addEventListener("abort",()=>{clearTimeout(timeoutId),reject(new McpError(ErrorCode.InvalidRequest,"Request cancelled"))},{once:!0})})}requestTaskStore(request,sessionId){let taskStore=this._taskStore;if(!taskStore)throw new Error("No task store configured");return{createTask:async taskParams=>{if(!request)throw new Error("No request provided");return await taskStore.createTask(taskParams,request.id,{method:request.method,params:request.params},sessionId)},getTask:async taskId=>{let task=await taskStore.getTask(taskId,sessionId);if(!task)throw new McpError(ErrorCode.InvalidParams,"Failed to retrieve task: Task not found");return task},storeTaskResult:async(taskId,status,result)=>{await taskStore.storeTaskResult(taskId,status,result,sessionId);let task=await taskStore.getTask(taskId,sessionId);if(task){let notification=TaskStatusNotificationSchema.parse({method:"notifications/tasks/status",params:task});await this.notification(notification),isTerminal(task.status)&&this._cleanupTaskProgressHandler(taskId)}},getTaskResult:taskId=>taskStore.getTaskResult(taskId,sessionId),updateTaskStatus:async(taskId,status,statusMessage)=>{let task=await taskStore.getTask(taskId,sessionId);if(!task)throw new McpError(ErrorCode.InvalidParams,`Task "${taskId}" not found - it may have been cleaned up`);if(isTerminal(task.status))throw new McpError(ErrorCode.InvalidParams,`Cannot update task "${taskId}" from terminal status "${task.status}" to "${status}". Terminal states (completed, failed, cancelled) cannot transition to other states.`);await taskStore.updateTaskStatus(taskId,status,statusMessage,sessionId);let updatedTask=await taskStore.getTask(taskId,sessionId);if(updatedTask){let notification=TaskStatusNotificationSchema.parse({method:"notifications/tasks/status",params:updatedTask});await this.notification(notification),isTerminal(updatedTask.status)&&this._cleanupTaskProgressHandler(taskId)}},listTasks:cursor=>taskStore.listTasks(cursor,sessionId)}}};function isPlainObject2(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)}function mergeCapabilities(base,additional){let result={...base};for(let key in additional){let k=key,addValue=additional[k];if(addValue===void 0)continue;let baseValue=result[k];isPlainObject2(baseValue)&&isPlainObject2(addValue)?result[k]={...baseValue,...addValue}:result[k]=addValue}return result}var import_ajv=__toESM(require_ajv(),1),import_ajv_formats=__toESM(require_dist(),1);function createDefaultAjvInstance(){let ajv=new import_ajv.default({strict:!1,validateFormats:!0,validateSchema:!1,allErrors:!0});return(0,import_ajv_formats.default)(ajv),ajv}var AjvJsonSchemaValidator=class{constructor(ajv){this._ajv=ajv??createDefaultAjvInstance()}getValidator(schema){let ajvValidator="$id"in schema&&typeof schema.$id=="string"?this._ajv.getSchema(schema.$id)??this._ajv.compile(schema):this._ajv.compile(schema);return input=>ajvValidator(input)?{valid:!0,data:input,errorMessage:void 0}:{valid:!1,data:void 0,errorMessage:this._ajv.errorsText(ajvValidator.errors)}}};var ExperimentalServerTasks=class{constructor(_server){this._server=_server}requestStream(request,resultSchema,options){return this._server.requestStream(request,resultSchema,options)}createMessageStream(params,options){let clientCapabilities=this._server.getClientCapabilities();if((params.tools||params.toolChoice)&&!clientCapabilities?.sampling?.tools)throw new Error("Client does not support sampling tools capability.");if(params.messages.length>0){let lastMessage=params.messages[params.messages.length-1],lastContent=Array.isArray(lastMessage.content)?lastMessage.content:[lastMessage.content],hasToolResults=lastContent.some(c=>c.type==="tool_result"),previousMessage=params.messages.length>1?params.messages[params.messages.length-2]:void 0,previousContent=previousMessage?Array.isArray(previousMessage.content)?previousMessage.content:[previousMessage.content]:[],hasPreviousToolUse=previousContent.some(c=>c.type==="tool_use");if(hasToolResults){if(lastContent.some(c=>c.type!=="tool_result"))throw new Error("The last message must contain only tool_result content if any is present");if(!hasPreviousToolUse)throw new Error("tool_result blocks are not matching any tool_use from the previous message")}if(hasPreviousToolUse){let toolUseIds=new Set(previousContent.filter(c=>c.type==="tool_use").map(c=>c.id)),toolResultIds=new Set(lastContent.filter(c=>c.type==="tool_result").map(c=>c.toolUseId));if(toolUseIds.size!==toolResultIds.size||![...toolUseIds].every(id=>toolResultIds.has(id)))throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match")}}return this.requestStream({method:"sampling/createMessage",params},CreateMessageResultSchema,options)}elicitInputStream(params,options){let clientCapabilities=this._server.getClientCapabilities(),mode=params.mode??"form";switch(mode){case"url":{if(!clientCapabilities?.elicitation?.url)throw new Error("Client does not support url elicitation.");break}case"form":{if(!clientCapabilities?.elicitation?.form)throw new Error("Client does not support form elicitation.");break}}let normalizedParams=mode==="form"&¶ms.mode===void 0?{...params,mode:"form"}:params;return this.requestStream({method:"elicitation/create",params:normalizedParams},ElicitResultSchema,options)}async getTask(taskId,options){return this._server.getTask({taskId},options)}async getTaskResult(taskId,resultSchema,options){return this._server.getTaskResult({taskId},resultSchema,options)}async listTasks(cursor,options){return this._server.listTasks(cursor?{cursor}:void 0,options)}async cancelTask(taskId,options){return this._server.cancelTask({taskId},options)}};function assertToolsCallTaskCapability(requests,method,entityName){if(!requests)throw new Error(`${entityName} does not support task creation (required for ${method})`);switch(method){case"tools/call":if(!requests.tools?.call)throw new Error(`${entityName} does not support task creation for tools/call (required for ${method})`);break;default:break}}function assertClientRequestTaskCapability(requests,method,entityName){if(!requests)throw new Error(`${entityName} does not support task creation (required for ${method})`);switch(method){case"sampling/createMessage":if(!requests.sampling?.createMessage)throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${method})`);break;case"elicitation/create":if(!requests.elicitation?.create)throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${method})`);break;default:break}}var Server=class extends Protocol{constructor(_serverInfo,options){super(options),this._serverInfo=_serverInfo,this._loggingLevels=new Map,this.LOG_LEVEL_SEVERITY=new Map(LoggingLevelSchema.options.map((level,index)=>[level,index])),this.isMessageIgnored=(level,sessionId)=>{let currentLevel=this._loggingLevels.get(sessionId);return currentLevel?this.LOG_LEVEL_SEVERITY.get(level)<this.LOG_LEVEL_SEVERITY.get(currentLevel):!1},this._capabilities=options?.capabilities??{},this._instructions=options?.instructions,this._jsonSchemaValidator=options?.jsonSchemaValidator??new AjvJsonSchemaValidator,this.setRequestHandler(InitializeRequestSchema,request=>this._oninitialize(request)),this.setNotificationHandler(InitializedNotificationSchema,()=>this.oninitialized?.()),this._capabilities.logging&&this.setRequestHandler(SetLevelRequestSchema,async(request,extra)=>{let transportSessionId=extra.sessionId||extra.requestInfo?.headers["mcp-session-id"]||void 0,{level}=request.params,parseResult=LoggingLevelSchema.safeParse(level);return parseResult.success&&this._loggingLevels.set(transportSessionId,parseResult.data),{}})}get experimental(){return this._experimental||(this._experimental={tasks:new ExperimentalServerTasks(this)}),this._experimental}registerCapabilities(capabilities){if(this.transport)throw new Error("Cannot register capabilities after connecting to transport");this._capabilities=mergeCapabilities(this._capabilities,capabilities)}setRequestHandler(requestSchema,handler){let methodSchema=getObjectShape(requestSchema)?.method;if(!methodSchema)throw new Error("Schema is missing a method literal");let methodValue;if(isZ4Schema(methodSchema)){let v4Schema=methodSchema;methodValue=v4Schema._zod?.def?.value??v4Schema.value}else{let v3Schema=methodSchema;methodValue=v3Schema._def?.value??v3Schema.value}if(typeof methodValue!="string")throw new Error("Schema method literal must be a string");if(methodValue==="tools/call"){let wrappedHandler=async(request,extra)=>{let validatedRequest=safeParse2(CallToolRequestSchema,request);if(!validatedRequest.success){let errorMessage=validatedRequest.error instanceof Error?validatedRequest.error.message:String(validatedRequest.error);throw new McpError(ErrorCode.InvalidParams,`Invalid tools/call request: ${errorMessage}`)}let{params}=validatedRequest.data,result=await Promise.resolve(handler(request,extra));if(params.task){let taskValidationResult=safeParse2(CreateTaskResultSchema,result);if(!taskValidationResult.success){let errorMessage=taskValidationResult.error instanceof Error?taskValidationResult.error.message:String(taskValidationResult.error);throw new McpError(ErrorCode.InvalidParams,`Invalid task creation result: ${errorMessage}`)}return taskValidationResult.data}let validationResult=safeParse2(CallToolResultSchema,result);if(!validationResult.success){let errorMessage=validationResult.error instanceof Error?validationResult.error.message:String(validationResult.error);throw new McpError(ErrorCode.InvalidParams,`Invalid tools/call result: ${errorMessage}`)}return validationResult.data};return super.setRequestHandler(requestSchema,wrappedHandler)}return super.setRequestHandler(requestSchema,handler)}assertCapabilityForMethod(method){switch(method){case"sampling/createMessage":if(!this._clientCapabilities?.sampling)throw new Error(`Client does not support sampling (required for ${method})`);break;case"elicitation/create":if(!this._clientCapabilities?.elicitation)throw new Error(`Client does not support elicitation (required for ${method})`);break;case"roots/list":if(!this._clientCapabilities?.roots)throw new Error(`Client does not support listing roots (required for ${method})`);break;case"ping":break}}assertNotificationCapability(method){switch(method){case"notifications/message":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${method})`);break;case"notifications/resources/updated":case"notifications/resources/list_changed":if(!this._capabilities.resources)throw new Error(`Server does not support notifying about resources (required for ${method})`);break;case"notifications/tools/list_changed":if(!this._capabilities.tools)throw new Error(`Server does not support notifying of tool list changes (required for ${method})`);break;case"notifications/prompts/list_changed":if(!this._capabilities.prompts)throw new Error(`Server does not support notifying of prompt list changes (required for ${method})`);break;case"notifications/elicitation/complete":if(!this._clientCapabilities?.elicitation?.url)throw new Error(`Client does not support URL elicitation (required for ${method})`);break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(method){if(this._capabilities)switch(method){case"completion/complete":if(!this._capabilities.completions)throw new Error(`Server does not support completions (required for ${method})`);break;case"logging/setLevel":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${method})`);break;case"prompts/get":case"prompts/list":if(!this._capabilities.prompts)throw new Error(`Server does not support prompts (required for ${method})`);break;case"resources/list":case"resources/templates/list":case"resources/read":if(!this._capabilities.resources)throw new Error(`Server does not support resources (required for ${method})`);break;case"tools/call":case"tools/list":if(!this._capabilities.tools)throw new Error(`Server does not support tools (required for ${method})`);break;case"tasks/get":case"tasks/list":case"tasks/result":case"tasks/cancel":if(!this._capabilities.tasks)throw new Error(`Server does not support tasks capability (required for ${method})`);break;case"ping":case"initialize":break}}assertTaskCapability(method){assertClientRequestTaskCapability(this._clientCapabilities?.tasks?.requests,method,"Client")}assertTaskHandlerCapability(method){this._capabilities&&assertToolsCallTaskCapability(this._capabilities.tasks?.requests,method,"Server")}async _oninitialize(request){let requestedVersion=request.params.protocolVersion;return this._clientCapabilities=request.params.capabilities,this._clientVersion=request.params.clientInfo,{protocolVersion:SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion)?requestedVersion:LATEST_PROTOCOL_VERSION,capabilities:this.getCapabilities(),serverInfo:this._serverInfo,...this._instructions&&{instructions:this._instructions}}}getClientCapabilities(){return this._clientCapabilities}getClientVersion(){return this._clientVersion}getCapabilities(){return this._capabilities}async ping(){return this.request({method:"ping"},EmptyResultSchema)}async createMessage(params,options){if((params.tools||params.toolChoice)&&!this._clientCapabilities?.sampling?.tools)throw new Error("Client does not support sampling tools capability.");if(params.messages.length>0){let lastMessage=params.messages[params.messages.length-1],lastContent=Array.isArray(lastMessage.content)?lastMessage.content:[lastMessage.content],hasToolResults=lastContent.some(c=>c.type==="tool_result"),previousMessage=params.messages.length>1?params.messages[params.messages.length-2]:void 0,previousContent=previousMessage?Array.isArray(previousMessage.content)?previousMessage.content:[previousMessage.content]:[],hasPreviousToolUse=previousContent.some(c=>c.type==="tool_use");if(hasToolResults){if(lastContent.some(c=>c.type!=="tool_result"))throw new Error("The last message must contain only tool_result content if any is present");if(!hasPreviousToolUse)throw new Error("tool_result blocks are not matching any tool_use from the previous message")}if(hasPreviousToolUse){let toolUseIds=new Set(previousContent.filter(c=>c.type==="tool_use").map(c=>c.id)),toolResultIds=new Set(lastContent.filter(c=>c.type==="tool_result").map(c=>c.toolUseId));if(toolUseIds.size!==toolResultIds.size||![...toolUseIds].every(id=>toolResultIds.has(id)))throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match")}}return params.tools?this.request({method:"sampling/createMessage",params},CreateMessageResultWithToolsSchema,options):this.request({method:"sampling/createMessage",params},CreateMessageResultSchema,options)}async elicitInput(params,options){switch(params.mode??"form"){case"url":{if(!this._clientCapabilities?.elicitation?.url)throw new Error("Client does not support url elicitation.");let urlParams=params;return this.request({method:"elicitation/create",params:urlParams},ElicitResultSchema,options)}case"form":{if(!this._clientCapabilities?.elicitation?.form)throw new Error("Client does not support form elicitation.");let formParams=params.mode==="form"?params:{...params,mode:"form"},result=await this.request({method:"elicitation/create",params:formParams},ElicitResultSchema,options);if(result.action==="accept"&&result.content&&formParams.requestedSchema)try{let validationResult=this._jsonSchemaValidator.getValidator(formParams.requestedSchema)(result.content);if(!validationResult.valid)throw new McpError(ErrorCode.InvalidParams,`Elicitation response content does not match requested schema: ${validationResult.errorMessage}`)}catch(error2){throw error2 instanceof McpError?error2:new McpError(ErrorCode.InternalError,`Error validating elicitation response: ${error2 instanceof Error?error2.message:String(error2)}`)}return result}}}createElicitationCompletionNotifier(elicitationId,options){if(!this._clientCapabilities?.elicitation?.url)throw new Error("Client does not support URL elicitation (required for notifications/elicitation/complete)");return()=>this.notification({method:"notifications/elicitation/complete",params:{elicitationId}},options)}async listRoots(params,options){return this.request({method:"roots/list",params},ListRootsResultSchema,options)}async sendLoggingMessage(params,sessionId){if(this._capabilities.logging&&!this.isMessageIgnored(params.level,sessionId))return this.notification({method:"notifications/message",params})}async sendResourceUpdated(params){return this.notification({method:"notifications/resources/updated",params})}async sendResourceListChanged(){return this.notification({method:"notifications/resources/list_changed"})}async sendToolListChanged(){return this.notification({method:"notifications/tools/list_changed"})}async sendPromptListChanged(){return this.notification({method:"notifications/prompts/list_changed"})}};import process3 from"node:process";var ReadBuffer=class{append(chunk){this._buffer=this._buffer?Buffer.concat([this._buffer,chunk]):chunk}readMessage(){if(!this._buffer)return null;let index=this._buffer.indexOf(`
|
|
48
48
|
`);if(index===-1)return null;let line=this._buffer.toString("utf8",0,index).replace(/\r$/,"");return this._buffer=this._buffer.subarray(index+1),deserializeMessage(line)}clear(){this._buffer=void 0}};function deserializeMessage(line){return JSONRPCMessageSchema.parse(JSON.parse(line))}function serializeMessage(message){return JSON.stringify(message)+`
|
|
49
|
-
`}var StdioServerTransport=class{constructor(_stdin=process3.stdin,_stdout=process3.stdout){this._stdin=_stdin,this._stdout=_stdout,this._readBuffer=new ReadBuffer,this._started=!1,this._ondata=chunk=>{this._readBuffer.append(chunk),this.processReadBuffer()},this._onerror=error2=>{this.onerror?.(error2)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(;;)try{let message=this._readBuffer.readMessage();if(message===null)break;this.onmessage?.(message)}catch(error2){this.onerror?.(error2)}}async close(){this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),this.onclose?.()}send(message){return new Promise(resolve=>{let json2=serializeMessage(message);this._stdout.write(json2)?resolve():this._stdout.once("drain",resolve)})}};import*as client from"@mearl/client";function asRecord(value){return value&&typeof value=="object"&&!Array.isArray(value)?value:null}function requiredString(value,name){let result=typeof value=="string"?value.trim():"";if(!result)throw new Error(`${name} must be a non-empty string`);return result}async function
|
|
49
|
+
`}var StdioServerTransport=class{constructor(_stdin=process3.stdin,_stdout=process3.stdout){this._stdin=_stdin,this._stdout=_stdout,this._readBuffer=new ReadBuffer,this._started=!1,this._ondata=chunk=>{this._readBuffer.append(chunk),this.processReadBuffer()},this._onerror=error2=>{this.onerror?.(error2)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(;;)try{let message=this._readBuffer.readMessage();if(message===null)break;this.onmessage?.(message)}catch(error2){this.onerror?.(error2)}}async close(){this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),this.onclose?.()}send(message){return new Promise(resolve=>{let json2=serializeMessage(message);this._stdout.write(json2)?resolve():this._stdout.once("drain",resolve)})}};import*as client from"@mearl/client";function asRecord(value){return value&&typeof value=="object"&&!Array.isArray(value)?value:null}function requiredString(value,name){let result=typeof value=="string"?value.trim():"";if(!result)throw new Error(`${name} must be a non-empty string`);return result}async function invokePluginTool(value,invoke2){let input=asRecord(value);if(!input)throw new Error("plugin arguments must be an object");let plugin=requiredString(input.plugin,"plugin"),command=requiredString(input.command,"command"),commandInput=input.input===void 0?{}:asRecord(input.input);if(!commandInput)throw new Error("input must be an object");let options={};if(input.browser!==void 0&&(options.browser=requiredString(input.browser,"browser")),input.timeoutSec!==void 0){if(typeof input.timeoutSec!="number"||!Number.isFinite(input.timeoutSec)||input.timeoutSec<=0)throw new Error("timeoutSec must be a positive number");options.timeoutSec=input.timeoutSec}return invoke2(plugin,{command,input:commandInput},options)}import{writeFileSync,appendFileSync,readFileSync,existsSync}from"fs";import{tmpdir}from"os";import{join,dirname}from"path";import{spawn}from"child_process";import{fileURLToPath}from"url";import{createRequire}from"module";var require2=createRequire(import.meta.url),MCP_SERVER_VERSION=require2("../package.json").version,BROWSER_DEVICE_PRESET_NAMES=["iphone-17-pro","iphone-17e","pixel-11","ipad-mini-a17-pro","galaxy-s26","pura-x-max","iphone-15-pro","iphone-se","pixel-8","ipad-mini","galaxy-s23"],MCP_TOOL_ACTIONS={browser_tab_checkpoint:"tab_checkpoint",browser_get_requests:"get_requests",browser_get_events:"get_events",browser_get_logs:"get_logs",browser_set_mock:"set_mock",browser_get_mocks:"get_mocks",browser_send_request:"send_request",browser_send_mtop_request:"send_mtop_request",browser_set_rule:"set_rule",browser_get_rules:"get_rules",browser_page_screenshot:"page_screenshot",browser_launch:"browser_launch",browser_close:"browser_close",browser_release:"browser_release",browser_tab_open:"tab_open",browser_tab_close:"tab_close",browser_tab_list:"tab_list",browser_page_click:"page_click",browser_page_drag:"page_drag",browser_page_type:"page_type",browser_page_scroll:"page_scroll",browser_page_hover:"page_hover",browser_page_eval:"page_eval",browser_page_inspect:"page_inspect",browser_page_snapshot:"page_snapshot",browser_page_press:"page_press",browser_page_wait:"page_wait",browser_page_navigate:"page_navigate",browser_page_upload:"page_upload",browser_page_frames:"page_frames",browser_set_device_emulation:"set_device_emulation",browser_set_app_profile:"set_app_profile",browser_set_timezone:"set_timezone",browser_get_cookie:"get_cookie",browser_set_cookie:"set_cookie",browser_run_actions:"run_actions",browser_list:"browser_list",browser_select_browser:"browser_select_browser",browser_request_domain_permission:"request_domain_permission"},PLUGIN_INVOKE_TOOL_NAME="plugin_invoke";var LOG_FILE=join(tmpdir(),"mearl-mcp-server.log"),log=(...args)=>{let msg=`[${new Date().toISOString()}] [MCP Server] ${args.join(" ")}
|
|
50
50
|
`;try{appendFileSync(LOG_FILE,msg)}catch{}console.error("[MCP Server]",...args)};function printCliHelp(){console.error(`mearl-mcp-server v${MCP_SERVER_VERSION}
|
|
51
51
|
|
|
52
52
|
Usage:
|
|
@@ -97,6 +97,6 @@ Largest fields per item:`,stats.largestFields.forEach(f=>{header+=`
|
|
|
97
97
|
${"─".repeat(60)}
|
|
98
98
|
|
|
99
99
|
${compactStr}`}]}let suggestions=getOptimizationSuggestions(toolName,args,result,stats),diagnostic={error:{code:"RESPONSE_TOO_LARGE",message:"The result exceeded the MCP response limit. Narrow the request and retry.",originalSizeBytes:compactSize,limitBytes:1048576},meta:stats.meta,largestFields:stats.largestFields?.map(field=>({...field,percentageOfTotal:Math.round(field.size/compactSize*100)})),suggestions:suggestions.length>0?suggestions:["Significantly reduce the data requested",'Use "fields" to extract only essential data',"Add filters to narrow down results"]};return[{type:"text",text:JSON.stringify(diagnostic,null,2)}]}async function main(){let rawArgs=process.argv.slice(2),cliArgs={forwardedArgs:[],mode:"server"};if(rawArgs.length>0)try{let{parseMcpArgs:parseMcpArgs2}=await Promise.resolve().then(()=>(init_cliArgs(),cliArgs_exports));cliArgs=await parseMcpArgs2(rawArgs)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),printCliHelp(),process.exitCode=2;return}if(cliArgs.mode==="help"){printCliHelp();return}if(cliArgs.mode==="version"){console.log(MCP_SERVER_VERSION);return}if(cliArgs.mode==="configure"){let __filename=fileURLToPath(import.meta.url),__dirname=dirname(__filename),configureScript=join(__dirname,"configure-bin.js");spawn(process.execPath,[configureScript,...cliArgs.forwardedArgs],{stdio:"inherit"}).on("exit",code=>{process.exit(code||0)});return}if(cliArgs.mode==="uninstall"){let __filename=fileURLToPath(import.meta.url),__dirname=dirname(__filename),uninstallScript=join(__dirname,"uninstall-bin.js");spawn(process.execPath,[uninstallScript,...cliArgs.forwardedArgs],{stdio:"inherit"}).on("exit",code=>{process.exit(code||0)});return}writeFileSync(LOG_FILE,`=== Mearl MCP Server Started at ${new Date().toISOString()} ===
|
|
100
|
-
`),log("Starting Mearl MCP Server..."),log("MCP Server initialized, will connect to Chrome Extension when tools are called");let server=new Server({name:"mearl",version:MCP_SERVER_VERSION},{capabilities:{tools:{}},instructions:"浏览器交互默认工作流:首次进入页面或导航后用 browser_page_snapshot 建立基线;AX 信息为空或过于稀疏时显式改用 mode=dom,不要固定获取两份快照。后续页面动作默认返回 { action, observation }。先检查 action.success;action.stage=precondition 表示尚未派发,应按 error 修正输入或刷新快照,且不读取已省略的 observation/diagnostics;action.stage=dispatch-uncertain 表示输入可能已送达,应先查看 action.attempt 中已解析的目标、命中、坐标、派发模式与输入序列状态,再用 observation 或最小范围快照核验状态,不直接重试;attempt 只用于诊断,不证明动作已生效。动作成功后再按 observation 处理:delta 读取 effects,navigation 在 ready=true 后重建快照,openedTabs 直接使用其 tabId。仅在 fullSnapshotRecommended=true 或需要读取滚动后的新视口时补最小范围快照;布局、样式和溢出诊断使用 browser_page_inspect,视觉任务使用 screenshot。无需页面观察时传 observe:false;需要动作期间的日志、请求或埋点时显式开启 diagnostics。page_eval 仅作为结构化 action 无法表达时的补充;不要在每次动作后固定追加 wait、snapshot 或 screenshot。"}),OBSERVE_INPUT_SCHEMA={type:["object","boolean"],default:{},description:"观察选项。默认开启内置观察(等待相关 DOM、XHR/Fetch/MTop 请求或导航稳定后返回页面变化信号);传 false 关闭,不影响显式请求的 diagnostics",properties:{quietMs:{type:"number",description:"最后一次 DOM 变化后等待的稳定窗口,默认 100ms"},firstChangeTimeoutMs:{type:"number",description:"没有发生 DOM 变化时最多等待多久,默认 500ms"},timeoutMs:{type:"number",description:"整个观察阶段的最大时间,默认 3000ms"},navigationGraceMs:{type:"number",description:"低信息量点击或按键后等待导航开始的基础宽限时间,默认 1000ms;若仍有网络活动会自动延长,有明确 effects 时不等待"},navigationTimeoutMs:{type:"number",description:"导航开始后等待页面就绪的最大时间,默认 15000ms"},networkIdleMs:{type:"number",description:"文档加载完成且相关 XHR/Fetch/MTop 请求归零后继续保持静默的时间,默认 500ms,用于跳过业务骨架屏"},contentReadyAfterMs:{type:"number",description:"动作开始后允许用结构稳定兜底的保护期,默认 5000ms,并自动限制在导航超时之前;保护期内仍优先等待网络静默"}}},DIAGNOSTICS_INPUT_SCHEMA={type:["object","boolean"],default:!1,description:"默认关闭。传 true 在动作执行前建立边界,并返回新增 error logs 和业务 requests;传对象可自定义通道与过滤,并按需开启 events",properties:{logs:{type:["object","boolean"],properties:{level:{type:"string",enum:["log","warn","error","info","all"]},limit:{type:"number",default:100},filter:{type:"string"}}},requests:{type:["object","boolean"],properties:{source:{type:"string",enum:["mtop","requests","all"]},count:{type:"number",default:100},filter:{type:"string"},includeBody:{type:"boolean",default:!1},includeHeaders:{type:"boolean",default:!1}}},events:{type:["object","boolean"],properties:{source:{type:"string",enum:["rum","aplus","arms","all"]},event_type:{type:"string"},filter:{type:"string"},limit:{type:"number",default:100},includeRaw:{type:"boolean",default:!1}}}}},tools=[{name:PLUGIN_TOOL_NAME,description:"调用当前 MCP Server 宿主上的 Mearl Skill 插件;缺失的 BUC 与 TDBank 插件会自动安装。插件名、子命令和 input 契约以对应 Skill 为准;BUC 使用 MCP Server 宿主身份,浏览器操作使用当前选择或显式指定的 Browser ID。",inputSchema:{type:"object",properties:{plugin:{type:"string",description:"已注册的插件名,或可按需安装的 buc、tdbank"},command:{type:"string",description:"插件注册的子命令名"},input:{type:"object",description:"传给插件 handler 的业务参数,省略时为空对象",additionalProperties:!0},browser:{type:"string",description:"可选目标浏览器 ID 或名称;省略时继承 browser_select_browser 选择的目标"},timeoutSec:{type:"number",description:"可选的浏览器底层调用超时秒数"}},required:["plugin","command"]}},{name:"browser_tab_checkpoint",description:"为目标标签页建立日志、请求和埋点的可靠增量边界,对应 mearl tab_checkpoint。返回的 cursor 可传给 browser_get_logs/browser_get_requests/browser_get_events 的 after。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID;不传时使用当前活动标签页"}}}},{name:"browser_get_requests",description:"获取指定标签页持续采集的 API 请求历史,包含请求、响应与 pending 状态。无需打开 DevTools panel;不传 after 时返回最新 N 条,传 after 时从最早未读项开始分页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取。不传则使用当前激活标签页"},count:{type:"number",description:"获取的请求数量,默认 10 个。最多可获取最近 1000 个请求",default:10},filter:{type:"string",description:'过滤 API 名称的正则表达式(可选)。例如: ".*\\.cart\\..*" 只返回购物车相关接口'},since:{type:"number",description:"从多久之前开始获取(秒)。例如: 60 表示获取最近 1 分钟内的请求"},after:{type:"string",description:"tab checkpoint 或上一次查询返回的 cursor,仅返回其后的请求"},includeBody:{type:"boolean",description:"是否包含请求体和响应体。false 时将省略 postData 和 responseBody 字段以减少数据量。默认 true",default:!0},includeHeaders:{type:"boolean",description:"是否包含请求头和响应头。false 时将省略 headers 和 responseHeaders 字段以减少数据量。默认 false",default:!1},maxBodySize:{type:"number",description:"单个请求/响应体的最大字节数。超过此大小将被截断。默认 50000(约 50KB)",default:5e4},fields:{type:"array",items:{type:"string"},description:'从响应体中提取指定字段,支持点号路径。例如: ["data.result.list", "data.total"] 只返回这些字段,大幅减少数据量'},keysOnly:{type:"boolean",description:"只返回数据结构(字段路径和类型),不返回实际值。设为 true 可先预览数据结构,再决定提取哪些字段。默认 false",default:!1},source:{type:"string",enum:["mtop","requests","all"],description:"数据源。mtop: mtop 接口(默认); requests: 普通 XHR/Fetch 请求; all: 全部业务请求"}}}},{name:"browser_get_events",description:"获取目标标签页后台采集的 RUM/aplus/ARMS 埋点事件,无需打开 DevTools panel。不传 after 时返回最新事件,传 after 时按完整上报批次从最早未读项开始分页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取。不传则使用当前激活标签页"},source:{type:"string",enum:["rum","aplus","arms","all"],description:"事件来源。rum: RUM 性能监控事件; aplus: aplus 埋点事件; arms: ARMS 前端监控事件; all: 全部(默认)",default:"all"},event_type:{type:"string",description:'事件类型正则过滤。例如: "view" 匹配页面 view 事件, "CLK" 匹配点击埋点'},filter:{type:"string",description:"正则过滤,匹配事件的 name 或 url 字段"},since:{type:"number",description:"从多久之前开始获取(秒)。例如: 60 表示获取最近 1 分钟内的事件"},after:{type:"string",description:"tab checkpoint 或上一次查询返回的 cursor,仅返回其后的埋点事件"},limit:{type:"number",description:"返回条数上限,默认 20",default:20},includeRaw:{type:"boolean",description:"是否返回完整 tracking URL、_raw 原始载荷和 _context 上下文;默认 false,仅返回解析后的精简字段",default:!1}}}},{name:"browser_get_logs",description:"获取指定标签页持续采集的 console API、未捕获异常和浏览器日志。无需打开 DevTools panel;不传 after 时返回最新 N 条,传 after 时从最早未读项开始分页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取;不传时使用当前活动标签页"},level:{type:"string",enum:["log","warn","error","info","all"],description:"日志级别过滤。log: 普通日志, warn: 警告, error: 错误, info: 信息, all: 所有级别。默认 all",default:"all"},since:{type:"number",description:"从多久之前开始获取日志(秒)。例如: 60 表示获取最近 1 分钟内的日志"},after:{type:"string",description:"tab checkpoint 或上一次查询返回的 cursor,仅返回其后的日志"},limit:{type:"number",description:"最大返回日志数量,默认 100;快照查询返回最新 N 条",default:100},filter:{type:"string",description:'过滤日志内容的正则表达式或字符串(可选)。支持正则表达式模式(不区分大小写),若正则无效则回退到字符串包含匹配。例如: "error|warning" 匹配包含 error 或 warning 的日志'}}}},{name:"browser_set_mock",description:"动态设置 API 接口的 Mock 数据,用于测试不同数据场景。修改后,浏览器中对该接口的所有请求都会返回 Mock 数据。适用于前端开发测试、边界情况验证、UI 状态测试等。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取;不传时使用当前活动标签页"},apiName:{type:"string",description:'API 名称或正则表达式模式。例如: "mtop.cart.query" 精确匹配, ".*\\.cart\\..*" 匹配所有购物车接口'},mockData:{type:["object","string"],description:'【方式一】直接设置完整 Mock 响应数据(JSON 对象)。传入后该接口将完全返回此数据,不再请求真实服务端。示例: {"data":{"result":{"list":[]}},"ret":["SUCCESS"]}。注意:mockData 和 fields 二选一,同时提供时优先使用 fields。大体积响应体可传文件引用字符串 "@/abs/resp.json"(从该文件读取,建议绝对路径)以减少上下文占用'},fields:{type:"array",description:"【方式二】基于真实响应修改指定字段。系统会先获取该接口的原始响应数据,然后按指定路径修改字段值。适合在真实数据基础上做微调",items:{type:"object",properties:{path:{type:"string",description:'字段路径,支持点号和数组索引。例如: "data.result.passengerList[0].name.text"'},value:{description:"要设置的值,可以是任意类型(字符串、数字、对象、数组等)"}},required:["path","value"]}},enabled:{type:"boolean",description:"是否启用 Mock。true: 启用 Mock, false: 禁用 Mock 恢复真实数据。默认 true",default:!0},duration:{type:"number",description:"完整响应时长(毫秒)。可选,mock 生效时的总耗时,绕过真实服务器精确控制(用于测试加载状态、超时等场景)"},conditions:{type:"object",additionalProperties:!0,description:"请求 query/body 字段的子集匹配规则;保留字段 $index 从 0 开始指定同一场景的调用顺序。相同 $index 再次设置会原地覆盖,超过最后一项后持续使用最后一项"},payloadFile:{type:"string",description:"从文件读取 mock 数据(JSON 格式)。当 mockData 很大时,可将完整 JSON 写入文件,通过此参数指定文件路径。文件内容会被解析为 mockData。注意:此参数与 mockData/fields 互斥,优先级最高"}},required:["apiName"]}},{name:"browser_get_mocks",description:"查看当前所有已设置的 Mock 配置,包括接口名称、是否启用、以及 Mock 数据内容。用于排查 Mock 是否生效、Mock 数据是否正确等问题。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取;不传时使用当前活动标签页"},apiName:{type:"string",description:'过滤指定接口,支持正则表达式。例如: "mtop.cart.query" 或 ".*\\.cart\\..*"。不传则返回所有 Mock'}}}},{name:"browser_send_request",description:"通过浏览器发起 HTTP 代理请求,自动携带目标域名的 Cookie(使用当前浏览器登录态)。支持 GET/POST/PUT/DELETE/PATCH、multipart 文本字段和本地文件上传,适用于需要用户登录态的接口调试、数据爬取、接口测试等场景。",inputSchema:{type:"object",properties:{url:{type:"string",description:"目标请求 URL,必须是完整 URL(含 http:// 或 https://)"},method:{type:"string",enum:["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"],description:"HTTP 请求方法,默认 GET",default:"GET"},headers:{type:"object",description:"自定义请求头(键值对),会与自动生成的 Cookie 头合并",additionalProperties:{type:"string"}},params:{type:"object",description:"URL 查询参数(键值对),会追加到 URL 中",additionalProperties:{type:"string"}},body:{description:"请求体。传入对象时自动序列化为 JSON 并设置 Content-Type: application/json;传入字符串时原样发送"},formData:{type:"object",description:"multipart/form-data 文本字段。字段值支持 string、number、boolean;不能与 body 同时使用",additionalProperties:{anyOf:[{type:"string"},{type:"number"},{type:"boolean"}]}},files:{type:"array",description:"multipart 文件列表,最多 20 个且总计不超过 40 MiB。本地调用优先传绝对 filePath;远程调用可传 base64,并同时提供 filename,Base64 文件内容总计不超过 7 MiB",maxItems:20,items:{type:"object",properties:{fieldName:{type:"string",description:"multipart 字段名,例如 file"},filePath:{type:"string",description:"Mearl native-host 所在机器上的绝对文件路径"},base64:{type:"string",description:"文件内容的 Base64;与 filePath 二选一"},filename:{type:"string",description:"上传文件名;使用 base64 时必填"},contentType:{type:"string",description:"文件 MIME 类型;默认根据文件名推断"}},required:["fieldName"],oneOf:[{required:["filePath"]},{required:["base64","filename"]}]}},withCookies:{type:"boolean",description:"是否自动携带浏览器中该域名的 Cookie,默认 true",default:!0},responseType:{type:"string",enum:["json","text","auto"],description:'响应格式。auto: 自动检测(默认); json: 强制解析为 JSON; text: 返回原始文本。注意:auto 模式下若 Content-Type 为图片/音视频/PDF/压缩包等二进制类型,body 将以 base64 字符串返回,bodyType 为 "base64"',default:"auto"},timeout:{type:"number",description:"请求超时时间(毫秒),默认 30000(30 秒)",default:3e4}},required:["url"]}},{name:"browser_send_mtop_request",description:"在当前浏览器页面上下文中发起 mtop API 请求。自动处理签名计算(md5)、Cookie 中的 token 提取、时间戳生成等,无需手动构造签名。适用于:调试 mtop 接口、验证接口返回数据、测试不同参数组合等场景。注意:需要当前页面已登录(有对应的 Cookie),且 DevTools 面板已打开。",inputSchema:{type:"object",properties:{api:{type:"string",description:'mtop API 名称,例如: "mtop.trade.order.create"、"mtop.fliggy.flyrs.render"。以 "mopen." 开头的会使用 mopen 签名算法'},data:{description:'请求数据(JSON 对象),即 mtop 请求中的 data 参数。例如: {"itemId": "12345"}'},version:{type:"string",description:'API 版本号,默认 "1.0"',default:"1.0"},method:{type:"string",enum:["GET","POST"],description:"HTTP 请求方法,默认 GET。POST 时 data 参数放在请求体中",default:"GET"},appKey:{type:"string",description:'appKey,默认 "12574478"'},env:{type:"string",enum:["prod","pre"],description:"请求环境。prod: 生产(默认,h5api.m.taobao.com); pre: 预发(h5api.wapa.taobao.com)",default:"prod"},timeout:{type:"number",description:"请求超时时间(毫秒),默认 10000(10 秒)",default:1e4}},required:["api"]}},{name:"browser_set_rule",description:"添加 Chrome declarativeNetRequest 规则,用于拦截、重定向或修改请求。规则持久化保存,浏览器重启后仍生效。支持:重定向请求到另一地址、修改请求/响应头、阻止请求、升级到 HTTPS 等。适用于:本地开发时代理到本地服务、修改请求头调试、拦截特定请求等。",inputSchema:{type:"object",properties:{actionType:{type:"string",enum:["redirect","block","allow","upgradeScheme","modifyHeaders"],description:"规则类型。redirect: 重定向请求到另一地址; block: 阻止请求; allow: 允许请求; upgradeScheme: 升级到 HTTPS; modifyHeaders: 修改请求/响应头"},filter:{type:"string",description:'URL 匹配规则(正则表达式)。例如: "^https://h5api\\.m\\.taobao\\.com/.*" 匹配所有淘宝 h5api 请求'},redirectUrl:{type:"string",description:"【redirect 类型必填】重定向目标 URL。支持正则替换占位符 \\1 \\2 等(引用 filter 中的捕获组)"},requestHeaders:{type:"array",description:"【modifyHeaders 类型】要修改的请求头列表",items:{type:"object",properties:{header:{type:"string",description:'请求头名称,如 "x-custom-header"'},operation:{type:"string",enum:["set","append","remove"],description:"set: 设置/覆盖; append: 追加; remove: 删除"},value:{type:"string",description:"请求头值(remove 时可省略)"}},required:["header","operation"]}},responseHeaders:{type:"array",description:"【modifyHeaders 类型】要修改的响应头列表",items:{type:"object",properties:{header:{type:"string",description:"响应头名称"},operation:{type:"string",enum:["set","append","remove"],description:"set: 设置/覆盖; append: 追加; remove: 删除"},value:{type:"string",description:"响应头值(remove 时可省略)"}},required:["header","operation"]}},initiatorDomains:{type:"string",description:'发起请求的域名限制(逗号分隔)。只有从这些域名发起的请求才会匹配此规则。例如: "taobao.com,tmall.com"'},resourceTypes:{type:"array",description:"资源类型限制。不填则匹配所有类型",items:{type:"string",enum:["main_frame","sub_frame","script","stylesheet","image","xmlhttprequest","websocket","other"]}},priority:{type:"number",description:"规则优先级,数字越大优先级越高。多个规则匹配同一请求时,优先级高的生效。默认 1",default:1},description:{type:"string",description:"规则描述,便于识别规则用途"}},required:["actionType","filter"]}},{name:"browser_get_rules",description:"查看当前存储的全部请求规则(含用户在插件 Options 面板手动配置的)。返回规则总开关状态和规则列表,字段结构与 browser_set_rule 入参对齐,用于确认规则是否生效或排查请求被意外重定向/修改的问题。",inputSchema:{type:"object",properties:{}}},{name:"browser_page_screenshot",description:'获取指定浏览器标签页的视觉截图,以 Base64 编码返回。支持全页截图或指定 CSS 选择器截取单个元素(类似 DevTools "Capture node screenshot")。适用于视觉判断、Canvas、跨域 iframe、UI 排查和保存快照;常规页面动作后优先读取其内置观察的增量结果,不要固定在每次动作后截图。',inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:"CSS 选择器。提供后只截取该元素区域(会自动滚动元素到可见区域),不提供则截取整个页面"},format:{type:"string",enum:["png","jpeg"],description:"截图格式。png: PNG 格式(无损,默认); jpeg: JPEG 格式(有损压缩,体积更小)",default:"png"},quality:{type:"number",description:"JPEG 质量(仅 format 为 jpeg 时有效)。范围 0-100,默认 80。数值越高质量越好但文件越大",default:80}},required:["tabId"]}},{name:"browser_launch",description:"启动浏览器实例。默认使用本地独立 Chrome;传已注册的 Provider ID 时,把该 Provider 声明的创建参数放在 providerOptions。配对实例会直接返回 pairing URL。具体 Provider 用法可运行 mearl <providerId> 查看。",inputSchema:{type:"object",properties:{name:{type:"string",description:"本地实例名称;使用默认 local Provider 时必填"},provider:{type:"string",description:"浏览器提供方,默认 local;也可传已注册的外部 Provider ID"},providerOptions:{type:"object",additionalProperties:!0,description:"所选外部 Provider 声明的结构化创建参数"},headless:{type:"boolean",description:"本地 Provider 是否使用 headless=new,默认 true"},userAgentMode:{type:"string",enum:["default","desktop"],description:"本地 UA 模式:default 使用默认 UA;desktop 使用匹配本机 Chrome 的 UA",default:"default"},persistent:{type:"boolean",description:"本地实例关闭后是否保留独立 Profile,默认 false",default:!1},url:{type:"string",description:"新浏览器打开的初始 URL"},executablePath:{type:"string",description:"Chrome 可执行文件路径;省略时自动发现,也可用环境变量配置"},copyCookieDomains:{oneOf:[{type:"array",items:{type:"string"}},{type:"string",enum:["mearl-services"]}],description:"从控制浏览器复制 Cookie。传域名数组时复制指定域;传 mearl-services 时同步 Mearl 依赖平台登录态。保留 HttpOnly/Secure/SameSite/过期时间等属性;域名数组中的非内置域需先授权。"}},anyOf:[{required:["name"]},{required:["provider"]}]}},{name:"browser_close",description:"关闭一个 Provider 托管浏览器;持久化数据默认按 Provider 策略保留,deleteProfile=true 时一并删除。名称有歧义时使用完整 browserId。",inputSchema:{type:"object",properties:{browser:{type:"string",description:"browser_launch 返回的 browserId 或实例名称"},deleteProfile:{type:"boolean",description:"是否强制删除 Provider 持久化数据,默认 false",default:!1}},required:["browser"]}},{name:"browser_release",description:"仅在用户明确要求结束调试、退出接管或清理会话资源时调用,不作为普通任务收尾。它会释放 debugger/CDP 控制和会话级临时效果,后续浏览器操作可自动重新建立控制;Provider 实例的生命周期操作由 Browser Manager 处理。",inputSchema:{type:"object",properties:{}}},{name:"browser_tab_open",description:"打开或按 URL 规则复用标签页。默认新建并等待加载完成;reuse=prefer 可优先复用,reuse=require 可限制为只复用。响应的 opened/reused 可用于判断流程结束时是否应关闭该 Tab。",inputSchema:{type:"object",properties:{url:{type:"string",description:"要打开的页面 URL"},active:{type:"boolean",description:"是否激活目标标签页并恢复最小化窗口。默认 false(后台打开);响应通过 activation 返回实际可见性",default:!1},openerTabId:{type:"number",description:"来源标签页 ID。侧边栏对话继续任务时传入,用于把新开或复用的标签页关联到同一对话"},closeExisting:{type:"boolean",description:"打开前是否先关闭 Agent 受控的已有标签页。默认 false",default:!1},group:{type:"string",description:"把新标签页加入指定标题的标签页分组(同窗口同名分组存在则加入,否则新建)。仅扩展模式支持,CDP 模式忽略"},reuse:{type:"string",enum:["never","prefer","require"],description:"never 始终新建;prefer 匹配到则复用、否则新建;require 只允许复用。默认 never",default:"never"},match:{type:"object",description:"复用标签页时的 URL 匹配规则",properties:{urlPattern:{type:"string",description:"支持 * 的完整 URL glob;省略时精确匹配 url"},ignoreSearch:{type:"boolean",description:"匹配时是否忽略 URL query,默认 false"},ignoreHash:{type:"boolean",description:"匹配时是否忽略 URL hash,默认 false"},onMultiple:{type:"string",enum:["error","first"],description:"匹配多个 Tab 时默认报错;first 显式取第一个"}}},restoreFocusOnClose:{type:"boolean",description:"新建 active Tab 关闭后是否恢复原活动标签页,默认 false",default:!1},emulation:{type:"object",description:"开 tab 即进入移动端模拟态,等价于随后立即调用 browser_set_device_emulation,但在导航前生效。deviceShell=true 时首屏就在 iframe WebView 与设备系统外壳中渲染。字段规则一致(无 enabled/reload)。",properties:{preset:{type:"string",enum:[...BROWSER_DEVICE_PRESET_NAMES],description:"内置设备预设,一键提供 viewport/DPR/UA。当前机型在前,旧机型 ID 继续兼容;可与下面字段组合,显式字段覆盖预设值"},width:{type:"number",description:"视口宽度(覆盖 preset)"},height:{type:"number",description:"视口高度(覆盖 preset)"},deviceScaleFactor:{type:"number",description:"devicePixelRatio(覆盖 preset)"},scale:{type:"number",exclusiveMinimum:0,description:"画面视觉比例,不改变视口 CSS 尺寸或 devicePixelRatio;必须为有限正数,默认 1"},mobile:{type:"boolean",description:"是否启用移动渲染模式。默认从 preset 推断,无 preset 默认 true"},userAgent:{type:"string",description:"自定义 User-Agent(覆盖 preset)。无 preset 时必填"},orientation:{type:"string",enum:["portrait","landscape"],description:"横竖屏,landscape 会对调宽高。默认 portrait"},touch:{type:"boolean",description:"是否启用触摸事件并把鼠标事件转成 touch。默认从 preset 推断;无 preset 时跟随 mobile"},deviceShell:{type:"boolean",description:"是否使用 iframe WebView 并渲染顶部状态栏与底部操作区,默认 false"},splitScreen:{type:"boolean",description:"是否在横屏设备外壳中将首页与业务页分置左右 WebView;仅与 appProfile、deviceShell=true、orientation=landscape 同时生效,默认 false"}}},appProfile:{type:"string",enum:[...client.APP_PROFILE_NAMES],description:"开 tab 即注入 App 客户端环境与 JSBridge(等价于随后调用 browser_set_app_profile,但在首次导航前生效)。不创建根 iframe;需要设备外壳时同时传 emulation.deviceShell=true"},os:{type:"string",enum:["ios","android"],description:"与 appProfile 配合;容器系统,默认 ios"},bridgeConfig:{type:"object",description:"与 appProfile 配合;声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}},不执行配置脚本"}},required:["url"]}},{name:"browser_tab_close",description:"关闭指定的浏览器标签页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"要关闭的标签页 ID(从 tab_open 或 tab_list 获取)"}},required:["tabId"]}},{name:"browser_tab_list",description:"列出当前浏览器窗口中所有标签页的信息,包括 ID、URL、标题和是否活动。",inputSchema:{type:"object",properties:{}}},{name:"browser_page_click",description:"点击页面元素;selector、text、point 三种定位方式必须且只能提供一种。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:`原生 CSS 选择器(如 "[aria-label='提交']"、"#login-btn")或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e3",必须带 "@" 前缀)。注意字段名是 "selector" 而非 "ref"。不支持 :has-text/:visible 等 Playwright 扩展语法。与 text/point 互斥。`},text:{type:"string",description:'按可见文本(accessibility name)定位。例如 "退款明细"。匹配到多个时会报错并列出候选——可加 role 或 exact:true 收敛,或用 page_snapshot 拿 @ref。与 selector/point 互斥。'},point:{type:"object",description:"按视口坐标点击(CSS 像素,左上角为原点)。selector 和 text 都不适用时使用。与 selector/text 互斥。",properties:{x:{type:"number",description:"横坐标(CSS 像素)"},y:{type:"number",description:"纵坐标(CSS 像素)"}},required:["x","y"]},role:{type:"string",description:'配合 text 使用,按 AX role 过滤消歧(如 "button"、"link"、"heading"、"StaticText")'},exact:{type:"boolean",description:"配合 text 使用,默认 true 精确匹配;false 时按子串匹配",default:!0},scope:{type:"string",description:'配合 text 使用,把 AX 文本匹配限制在指定 CSS 元素或 snapshot ref(如 "@e12")子树内'},clickMode:{type:"string",enum:["auto","dom","mouse","touch"],description:"默认 auto:可见页使用匹配设备的可信输入,隐藏页使用 DOM;dom/mouse/touch 可强制指定派发方式",default:"auto"},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId"]}},{name:"browser_page_drag",description:"连续拖动页面元素或视口坐标,适用于轮播图、滑块、Canvas 手势和拖放。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},from:{description:"拖动起点:CSS/@eN selector,或 {x,y} 视口坐标(CSS 像素)",anyOf:[{type:"string"},{type:"object",properties:{x:{type:"number"},y:{type:"number"}},required:["x","y"]}]},to:{description:"拖动终点:CSS/@eN selector,或 {x,y} 视口坐标(CSS 像素)",anyOf:[{type:"string"},{type:"object",properties:{x:{type:"number"},y:{type:"number"}},required:["x","y"]}]},dragMode:{type:"string",enum:["auto","dom","mouse","touch"],description:"默认 auto:可见页使用匹配设备的可信输入,隐藏页使用 DOM;dom/mouse/touch 可强制指定派发方式",default:"auto"},durationMs:{type:"number",minimum:0,maximum:5e3,description:"拖动持续时间(毫秒),默认 400;内部自动分段移动",default:400},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","from","to"]}},{name:"browser_page_type",description:"向输入框填写文本,兼容 React 等框架的受控组件。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:'原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e6",必须带 "@" 前缀)。字段名是 "selector"。不支持 :has-text/:visible 等 Playwright 扩展。'},text:{type:"string",description:"要输入的文本内容"},clearFirst:{type:"boolean",description:"是否先清空输入框原有内容。默认 true",default:!0},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","selector","text"]}},{name:"browser_page_scroll",description:'按方向滚动页面或指定容器;页面根不可滚动时自动发现活动滚动区,containerPolicy="nearest" 可从子节点解析最近的可滚动祖先。',inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},direction:{type:"string",enum:["up","down","top","bottom"],description:"滚动方向"},distance:{type:"number",description:"滚动距离(像素),仅 up/down 方向有效。默认 600",default:600},selector:{type:"string",description:'目标滚动容器的原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e6",必须带 "@" 前缀);不传时滚动页面。'},containerPolicy:{type:"string",enum:["self","nearest"],description:"默认 self,要求 selector 本身可滚动;nearest 会在其不可滚动时使用最近的可滚动祖先"},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","direction"]}},{name:"browser_page_hover",description:"将鼠标悬停在页面元素上。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:'原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e1",必须带 "@" 前缀)。字段名是 "selector"。不支持 :has-text/:visible 等 Playwright 扩展。'},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","selector"]}},{name:"browser_page_eval",description:"在页面上下文中执行 JavaScript 表达式,作为结构化页面 action 无法表达时的补充。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},expression:{type:"string",description:"要执行的 JavaScript 表达式"},frameId:{type:"string",description:"目标 frame 的 CDP frameId。不传则在主 frame 中执行。可通过 browser_page_frames 获取"},awaitPromise:{type:"boolean",description:"是否等待表达式返回的 Promise,默认 true",default:!0},observe:{...OBSERVE_INPUT_SCHEMA,type:"object",description:"仅在表达式会修改页面且需要观察结果时显式传入;不传时轻量执行并直接返回结果"},diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","expression"]}},{name:"browser_page_inspect",description:"查询 DOM 元素数量、边框盒、计算样式、命中遮挡、溢出尺寸和最近滚动容器;也可读取 DevTools 当前选区或直接扫描全页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:'原生 CSS、page_snapshot 返回的 ref(如 "@e8"),或 DevTools Elements 当前选区 "$0";全页溢出诊断时可省略'},filter:{type:"string",enum:["all","overflowing","horizontal-overflow","vertical-overflow","scrollable"],description:"结果过滤;省略 selector 时必须指定非 all 的过滤条件"},styles:{type:"array",items:{type:"string"},description:"要返回的计算样式属性;默认 display/position/box-sizing/overflow-x/overflow-y"},maxResults:{type:"number",minimum:1,maximum:100,description:"最多返回的明细数,默认 20;未触发 scanTruncated 时 count 为完整命中数"},includeOuterHTML:{type:"boolean",description:"是否返回 outerHTML(最多 3000 字符);$0 默认 true,其他目标默认 false"}},required:["tabId"]}},{name:"browser_page_snapshot",description:"获取带 @ref 的页面结构树;默认使用无障碍树,AX 信息缺失时可显式读取渲染 DOM。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},depth:{type:"number",description:"无障碍树的最大深度。默认 15,增大可获取更深层元素",default:15},mode:{type:"string",enum:["full","interactive","viewport","dom"],description:"full 为完整 AX 树;interactive 只保留当前视口内的 AX 语义控件,无控件时回退到 AX viewport;viewport 为当前可视 AX 树;dom 显式返回实际渲染文本、原生控件、显式 role 和高置信 clickable 节点。默认 full"},rootSelector:{type:"string",description:"只获取指定 CSS 元素的局部子树,可与 mode 组合;与 rootRef 互斥"},rootRef:{type:"string",description:'以已有 snapshot ref(如 "@e8")为根获取局部子树'},ancestorDepth:{type:"number",description:"rootRef 向上扩展的 DOM 祖先层数,默认 0,最大 20",minimum:0,maximum:20},query:{type:"object",description:"服务端按 name / role 过滤当前模式的树,只保留命中节点及祖先路径",properties:{text:{type:"string",description:"要匹配的 accessibility name"},role:{type:"string",description:"要匹配的 AX role"},exact:{type:"boolean",description:"text 默认精确匹配;false 时按子串匹配"}}},maxNodes:{type:"number",description:"最多输出节点数;超出时保留首尾。0 表示不限制"},maxChars:{type:"number",description:"最多输出字符数,默认 60000;超出时保留首尾。0 表示不限制"}},required:["tabId"]}},{name:"browser_page_press",description:"在页面中按下键盘按键或组合键。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},key:{type:"string",description:"按键名称。支持:Enter, Tab, Escape, Backspace, Delete, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, Home, End, PageUp, PageDown, Space"},modifiers:{type:"array",items:{type:"string"},description:'修饰键数组,如 ["Alt", "Shift", "Control", "Meta"]'},pressMode:{type:"string",enum:["auto","dom","keyboard"],description:"派发模式;auto 默认在隐藏页降级为 DOM 键盘事件"},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","key"]}},{name:"browser_page_wait",description:"独立等待接口:仅用于没有前置动作时等待指定时间、已知 selector 状态、可见文本或页面 condition。四种模式必须且只能提供一个;点击、输入后的异步稳定判断由页面交互工具内置的观察完成。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},time:{type:"number",description:"固定等待毫秒数,与 selector/text/condition 四选一"},selector:{type:"string",description:"CSS 选择器,与 time/text/condition 四选一"},state:{type:"string",enum:["attached","detached","visible","hidden"],description:"selector 的目标状态,默认 attached",default:"attached"},text:{type:"string",description:"等待页面出现的可见文本,与 time/selector/condition 四选一"},exact:{type:"boolean",description:"text 是否精确匹配,默认 false",default:!1},condition:{type:"string",description:"在页面主上下文轮询的 JavaScript 表达式,返回 truthy 时结束,支持 Promise;与 time/selector/text 四选一"},timeout:{type:"number",description:"等待超时时间(毫秒),默认 10000ms",default:1e4},interval:{type:"number",description:"selector/condition 的轮询间隔(毫秒),默认 200ms",default:200}},required:["tabId"]}},{name:"browser_page_navigate",description:'在指定标签页中导航到 URL、设置 refresh:true 重新加载,或用 history:"back"|"forward" 沿浏览历史移动。三种模式互斥,返回最终 URL 和标题。',inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},url:{type:"string",description:"要导航到的 URL;与 refresh/history 互斥"},refresh:{type:"boolean",description:"为 true 时直接重新加载当前页面;与 url/history 互斥",default:!1},history:{type:"string",enum:["back","forward"],description:"沿当前标签页浏览历史后退或前进;与 url/refresh 互斥"}},required:["tabId"]}},{name:"browser_page_upload",description:'向 <input type="file"> 元素上传一个或多个本地文件。',inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:'原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e5",必须带 "@" 前缀),用于定位 <input type="file"> 元素。字段名是 "selector"。'},filePaths:{type:"array",items:{type:"string"},description:'要上传的本地文件路径数组,如 ["/Users/me/photo.jpg"]'},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","selector","filePaths"]}},{name:"browser_page_frames",description:"列出主 frame 和 iframe,返回可供 browser_page_eval 使用的 frameId。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"}},required:["tabId"]}},{name:"browser_set_device_emulation",description:"把目标标签页切换为移动端模拟态:视口尺寸 / DPR / UA / 触摸事件按指定设备生效,并可独立调整视觉比例。deviceShell=true 时把业务页放入 iframe WebView,并在外层渲染顶部状态栏与底部操作区;false/省略时保持纯 CDP 模拟。作用域仅限该 tab,启用后默认 reload,enabled=false 清除模拟与设备外壳。",inputSchema:{type:"object",properties:{enabled:{type:"boolean",description:"必填。true=启用模拟(按 preset/参数生效),false=清除模拟回到桌面态"},preset:{type:"string",enum:[...BROWSER_DEVICE_PRESET_NAMES],description:"内置设备预设,一键提供 viewport/DPR/UA。当前机型在前,旧机型 ID 继续兼容;可与下面的字段组合,显式字段会覆盖预设值"},width:{type:"number",description:"视口宽度(覆盖 preset)"},height:{type:"number",description:"视口高度(覆盖 preset)"},deviceScaleFactor:{type:"number",description:"devicePixelRatio(覆盖 preset)"},scale:{type:"number",exclusiveMinimum:0,description:"画面视觉比例,不改变视口 CSS 尺寸或 devicePixelRatio;必须为有限正数,默认 1"},mobile:{type:"boolean",description:"是否启用移动渲染模式(影响 hover/pointer media query、viewport meta 行为)。默认从 preset 推断,无 preset 默认 true"},userAgent:{type:"string",description:"自定义 User-Agent(覆盖 preset)"},orientation:{type:"string",enum:["portrait","landscape"],description:"横竖屏,landscape 会对调宽高。默认 portrait"},touch:{type:"boolean",description:"是否启用触摸事件并把鼠标事件转成 touch。默认从 preset 推断;无 preset 时跟随 mobile"},deviceShell:{type:"boolean",description:"是否使用 iframe WebView 并渲染顶部状态栏与底部操作区,默认 false"},splitScreen:{type:"boolean",description:"是否在横屏 App 容器中将首页与业务页分置左右 WebView;仅在当前已启用 App 档案、deviceShell=true、orientation=landscape 时生效,默认 false"},reload:{type:"boolean",description:"启用模拟后是否重载页面(让 JS 读到新的 navigator.userAgent / window.innerWidth)。默认 true"},tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"}},required:["tabId","enabled"]}},{name:"browser_set_app_profile",description:"设置目标标签页的 App 客户端 UA、环境变量、JSBridge 与桥协议,也可设置插件的 MTop 页面接口环境。传 emulation 时由同一个调用联动设备模拟与 iframe 系统外壳;省略 emulation 时不改变设备状态。",inputSchema:{type:"object",properties:{enabled:{type:"boolean",description:"必填。true=启用容器模拟,false=清除并还原设备模拟"},profile:{type:"string",enum:[...client.APP_PROFILE_NAMES],description:"容器档案名(enabled=true 时必填),决定 UA/桥对象/环境判断特征"},os:{type:"string",enum:["ios","android"],description:"容器系统,默认 ios"},appVersion:{type:"string",description:"覆盖档案默认 App 版本号"},deviceModel:{type:"string",description:"Android 机型名(拼入 UA 与 __DEVICE_MODEL__)"},bridgeConfig:{type:"object",description:"声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}};扩展本地同档案配置会先合并"},mtopEnv:{type:"string",enum:["default","prod","pre"],description:"可选 MTop 页面接口环境。default 关闭环境改写;省略时保持当前设置。扩展模式与插件设置页共享并全局生效,CDP 模式仅作用于目标 tab。"},emulation:{type:"object",description:"可选设备联动参数;字段覆盖档案推荐设备,空对象使用推荐设备,deviceShell 默认 true。省略时不设置或清除设备。",properties:{preset:{type:"string",enum:[...BROWSER_DEVICE_PRESET_NAMES]},width:{type:"number"},height:{type:"number"},deviceScaleFactor:{type:"number"},scale:{type:"number",exclusiveMinimum:0},mobile:{type:"boolean"},userAgent:{type:"string"},orientation:{type:"string",enum:["portrait","landscape"]},touch:{type:"boolean"},deviceShell:{type:"boolean",description:"是否使用根 iframe WebView 并显示系统栏;在 emulation 内默认 true"},splitScreen:{type:"boolean",description:"是否在横屏设备外壳中将首页与业务页分置左右 WebView;仅与 deviceShell=true、orientation=landscape 同时生效,默认 false"}}},reload:{type:"boolean",description:"应用/清除后是否重载页面,默认 true"},tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"}},required:["tabId","enabled"]}},{name:"browser_set_timezone",description:"覆盖目标标签页的时区,作用域仅限该 tab,立即影响 Date / Intl 等页面时间 API。timezone 使用 IANA 时区标识(如 Asia/Shanghai、America/New_York);传空字符串恢复浏览器默认时区。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},timezone:{type:"string",description:"IANA 时区标识;空字符串表示清除覆盖"}},required:["tabId","timezone"]}},{name:"browser_get_cookie",description:"从目标浏览器读取一个指定非分区 Cookie,用于验证页面分支、实验或当前账号标识。必须明确传 Cookie 名,不支持列举全部 Cookie;HttpOnly Cookie 会被拒绝,禁止读取认证 Token。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},name:{type:"string",description:"Cookie 名称"},url:{type:"string",description:"可选 Cookie 查询 URL;省略时使用当前标签页 URL"},domain:{type:"string",description:"可选精确域过滤,只允许 Cookie 查询 URL 的 host 或它的父域"},path:{type:"string",description:"可选精确 path 过滤"}},required:["tabId","name"]}},{name:"browser_set_cookie",description:"修改当前标签页使用的一个指定非分区 session Cookie。不枚举、不读取其它 Cookie;未传 domain 时只写当前 host,显式传域时只允许当前 host 或它的父域。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},name:{type:"string",description:"Cookie 名称"},value:{type:"string",description:"Cookie 值,可传空字符串;空字符串不会删除 Cookie"},domain:{type:"string",description:"Cookie 域,默认当前 host;只允许当前 host 或它的父域"},path:{type:"string",description:"Cookie path,默认 /"},reload:{type:"boolean",description:"设置后是否刷新当前页面,默认 false"}},required:["tabId","name","value"]}},{name:"browser_run_actions",description:"批量顺序执行多个无需中间判断的原子操作,适合 hover→click 等必须紧密连续的序列。步骤内的页面动作不带内置观察;遇到第一个失败步骤立即停止,且不能嵌套 run_actions。若下一步需要根据页面变化决定,优先逐步使用带观察的页面交互工具;不要用本工具固化「点击→等待→截图」循环。",inputSchema:{type:"object",properties:{actions:{type:"array",description:"要依次执行的 action 列表",items:{type:"object",properties:{action:{type:"string",description:"action 名称(不带 browser_ 前缀),如 page_hover、page_click;仅组合无需中间判断的步骤"},data:{type:"object",description:"该 action 的参数(与单独调用时相同)"}},required:["action"]}},tabId:{type:"number",description:"所有步骤共享的目标标签页 ID。步骤自身指定的 tabId 优先级更高"}},required:["tabId","actions"]}},{name:"browser_list",description:"列出所有浏览器。返回普通浏览器和 Provider 托管浏览器的 browserId、名称、类型、连接状态、稳定元数据及当前默认目标,但不返回带临时凭据的浏览器访问地址。只有 status=connected 的浏览器可用于后续操作。",inputSchema:{type:"object",properties:{}}},{name:"browser_select_browser",description:"选择后续所有浏览器操作的默认目标浏览器(有多个浏览器连接时)。传入 browser_list 返回且 status=connected 的 browserId 或名称即可锁定;传空字符串则清除锁定,回到自动模式(操作最近聚焦的浏览器)。",inputSchema:{type:"object",properties:{browser:{type:"string",description:"目标浏览器的 browserId / 名称;空字符串表示清除锁定、恢复自动选择"}},required:["browser"]}},{name:"browser_request_domain_permission",description:"申请访问指定域名的权限。调用后浏览器会弹出确认窗口让用户授权(90 秒超时),返回 granted 表示是否已获得授权。扩展模式下发送非内置域的 HTTP 请求(browser_send_request)前需先获得用户授权。",inputSchema:{type:"object",properties:{domain:{type:"string",description:"需要授权的域名,如 example.com"}},required:["domain"]}}];server.setRequestHandler(ListToolsRequestSchema,async()=>({tools})),server.setRequestHandler(CallToolRequestSchema,async request=>{let{arguments:args}=request.params,name=request.params.name==="browser_capture_checkpoint"?"browser_tab_checkpoint":request.params.name;try{if(name!==PLUGIN_TOOL_NAME&&!(name in MCP_TOOL_ACTIONS))throw new Error(`Unknown tool: ${name}`);let toolName=name,result;switch(toolName){case PLUGIN_TOOL_NAME:{result=await invokeMearlPluginTool(args,client.invokePlugin);break}case"browser_tab_checkpoint":{let{tabId}=args;result=await client.tabCheckpoint({tabId});break}case"browser_get_requests":{let{tabId,count=10,filter,since,after,includeBody=!0,includeHeaders=!1,maxBodySize=5e4,fields,keysOnly=!1,source}=args;result=await client.getRequests({tabId,count,filter,since,after,includeBody,includeHeaders,maxBodySize,fields,keysOnly,source});break}case"browser_get_events":{let{tabId,source="all",event_type,filter,since,after,limit=20,includeRaw=!1}=args;result=await client.getEvents({tabId,source,event_type,filter,since,after,limit,includeRaw});break}case"browser_get_logs":{let{tabId,level="all",since,after,limit=100,filter}=args;result=await client.getLogs({tabId,level,since,after,limit,filter});break}case"browser_set_mock":{let{payloadFile}=args,{tabId,apiName,mockData,fields,enabled,duration:duration3,conditions}=args;if(enabled=enabled??!0,payloadFile){if(!existsSync(payloadFile))throw new Error(`Payload file not found: ${payloadFile}`);let fileContent=readFileSync(payloadFile,"utf-8"),fileData=JSON.parse(fileContent);fileData.tabId!==void 0&&(tabId=fileData.tabId),fileData.apiName&&(apiName=fileData.apiName),fileData.mockData!==void 0&&(mockData=fileData.mockData),fileData.fields!==void 0&&(fields=fileData.fields),fileData.enabled!==void 0&&(enabled=fileData.enabled),fileData.duration!==void 0&&(duration3=fileData.duration),fileData.conditions!==void 0&&(conditions=fileData.conditions)}result=await client.setMock({tabId,apiName,mockData,fields,enabled,duration:duration3,conditions});break}case"browser_get_mocks":{let{tabId,apiName}=args;result=await client.getMocks({tabId,apiName});break}case"browser_send_request":{result=await client.sendRequest(args);break}case"browser_send_mtop_request":{let{api,data,version:version2,method,appKey,env,timeout}=args;result=await client.sendMtopRequest({api,data,version:version2,method,appKey,env,timeout});break}case"browser_set_rule":{result=await client.setRule(args);break}case"browser_get_rules":{result=await client.getRules();break}case"browser_page_screenshot":{let{format="png",quality=80,selector,tabId}=args;return result=await client.pageScreenshot({format,quality,selector,tabId}),{content:[{type:"image",data:result.data,mimeType:result.meta.format==="jpeg"?"image/jpeg":"image/png"},{type:"text",text:`Screenshot captured: ${result.meta.width}x${result.meta.height} ${result.meta.format.toUpperCase()} (${Math.round(result.meta.size/1024)}KB)
|
|
100
|
+
`),log("Starting Mearl MCP Server..."),log("MCP Server initialized, will connect to Chrome Extension when tools are called");let server=new Server({name:"mearl",version:MCP_SERVER_VERSION},{capabilities:{tools:{}},instructions:"浏览器交互默认工作流:首次进入页面或导航后用 browser_page_snapshot 建立基线;AX 信息为空或过于稀疏时显式改用 mode=dom,不要固定获取两份快照。后续页面动作默认返回 { action, observation }。先检查 action.success;action.stage=precondition 表示尚未派发,应按 error 修正输入或刷新快照,且不读取已省略的 observation/diagnostics;action.stage=dispatch-uncertain 表示输入可能已送达,应先查看 action.attempt 中已解析的目标、命中、坐标、派发模式与输入序列状态,再用 observation 或最小范围快照核验状态,不直接重试;attempt 只用于诊断,不证明动作已生效。动作成功后再按 observation 处理:delta 读取 effects,navigation 在 ready=true 后重建快照,openedTabs 直接使用其 tabId。仅在 fullSnapshotRecommended=true 或需要读取滚动后的新视口时补最小范围快照;布局、样式和溢出诊断使用 browser_page_inspect,视觉任务使用 screenshot。无需页面观察时传 observe:false;需要动作期间的日志、请求或埋点时显式开启 diagnostics。page_eval 仅作为结构化 action 无法表达时的补充;不要在每次动作后固定追加 wait、snapshot 或 screenshot。"}),OBSERVE_INPUT_SCHEMA={type:["object","boolean"],default:{},description:"观察选项。默认开启内置观察(等待相关 DOM、XHR/Fetch/MTop 请求或导航稳定后返回页面变化信号);传 false 关闭,不影响显式请求的 diagnostics",properties:{quietMs:{type:"number",description:"最后一次 DOM 变化后等待的稳定窗口,默认 100ms"},firstChangeTimeoutMs:{type:"number",description:"没有发生 DOM 变化时最多等待多久,默认 500ms"},timeoutMs:{type:"number",description:"整个观察阶段的最大时间,默认 3000ms"},navigationGraceMs:{type:"number",description:"低信息量点击或按键后等待导航开始的基础宽限时间,默认 1000ms;若仍有网络活动会自动延长,有明确 effects 时不等待"},navigationTimeoutMs:{type:"number",description:"导航开始后等待页面就绪的最大时间,默认 15000ms"},networkIdleMs:{type:"number",description:"文档加载完成且相关 XHR/Fetch/MTop 请求归零后继续保持静默的时间,默认 500ms,用于跳过业务骨架屏"},contentReadyAfterMs:{type:"number",description:"动作开始后允许用结构稳定兜底的保护期,默认 5000ms,并自动限制在导航超时之前;保护期内仍优先等待网络静默"}}},DIAGNOSTICS_INPUT_SCHEMA={type:["object","boolean"],default:!1,description:"默认关闭。传 true 在动作执行前建立边界,并返回新增 error logs 和业务 requests;传对象可自定义通道与过滤,并按需开启 events",properties:{logs:{type:["object","boolean"],properties:{level:{type:"string",enum:["log","warn","error","info","all"]},limit:{type:"number",default:100},filter:{type:"string"}}},requests:{type:["object","boolean"],properties:{source:{type:"string",enum:["mtop","requests","all"]},count:{type:"number",default:100},filter:{type:"string"},includeBody:{type:"boolean",default:!1},includeHeaders:{type:"boolean",default:!1}}},events:{type:["object","boolean"],properties:{source:{type:"string",enum:["rum","aplus","arms","all"]},event_type:{type:"string"},filter:{type:"string"},limit:{type:"number",default:100},includeRaw:{type:"boolean",default:!1}}}}},tools=[{name:PLUGIN_INVOKE_TOOL_NAME,description:"调用当前 MCP Server 宿主上的 Mearl Skill 插件,对应 CLI 的 mearl <plugin>。缺失的 BUC 与 TDBank 插件会自动安装。插件名、子命令和 input 契约以对应 Skill 为准;BUC 使用 MCP Server 宿主身份,浏览器操作使用当前选择或显式指定的 Browser ID。",inputSchema:{type:"object",properties:{plugin:{type:"string",description:"已注册的插件名,或可按需安装的 buc、tdbank"},command:{type:"string",description:"插件注册的子命令名"},input:{type:"object",description:"传给插件 handler 的业务参数,省略时为空对象",additionalProperties:!0},browser:{type:"string",description:"可选目标浏览器 ID 或名称;省略时继承 browser_select_browser 选择的目标"},timeoutSec:{type:"number",description:"可选的浏览器底层调用超时秒数"}},required:["plugin","command"]}},{name:"browser_tab_checkpoint",description:"为目标标签页建立日志、请求和埋点的可靠增量边界,对应 mearl tab_checkpoint。返回的 cursor 可传给 browser_get_logs/browser_get_requests/browser_get_events 的 after。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID;不传时使用当前活动标签页"}}}},{name:"browser_get_requests",description:"获取指定标签页持续采集的 API 请求历史,包含请求、响应与 pending 状态。无需打开 DevTools panel;不传 after 时返回最新 N 条,传 after 时从最早未读项开始分页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取。不传则使用当前激活标签页"},count:{type:"number",description:"获取的请求数量,默认 10 个。最多可获取最近 1000 个请求",default:10},filter:{type:"string",description:'过滤 API 名称的正则表达式(可选)。例如: ".*\\.cart\\..*" 只返回购物车相关接口'},since:{type:"number",description:"从多久之前开始获取(秒)。例如: 60 表示获取最近 1 分钟内的请求"},after:{type:"string",description:"tab checkpoint 或上一次查询返回的 cursor,仅返回其后的请求"},includeBody:{type:"boolean",description:"是否包含请求体和响应体。false 时将省略 postData 和 responseBody 字段以减少数据量。默认 true",default:!0},includeHeaders:{type:"boolean",description:"是否包含请求头和响应头。false 时将省略 headers 和 responseHeaders 字段以减少数据量。默认 false",default:!1},maxBodySize:{type:"number",description:"单个请求/响应体的最大字节数。超过此大小将被截断。默认 50000(约 50KB)",default:5e4},fields:{type:"array",items:{type:"string"},description:'从响应体中提取指定字段,支持点号路径。例如: ["data.result.list", "data.total"] 只返回这些字段,大幅减少数据量'},keysOnly:{type:"boolean",description:"只返回数据结构(字段路径和类型),不返回实际值。设为 true 可先预览数据结构,再决定提取哪些字段。默认 false",default:!1},source:{type:"string",enum:["mtop","requests","all"],description:"数据源。mtop: mtop 接口(默认); requests: 普通 XHR/Fetch 请求; all: 全部业务请求"}}}},{name:"browser_get_events",description:"获取目标标签页后台采集的 RUM/aplus/ARMS 埋点事件,无需打开 DevTools panel。不传 after 时返回最新事件,传 after 时按完整上报批次从最早未读项开始分页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取。不传则使用当前激活标签页"},source:{type:"string",enum:["rum","aplus","arms","all"],description:"事件来源。rum: RUM 性能监控事件; aplus: aplus 埋点事件; arms: ARMS 前端监控事件; all: 全部(默认)",default:"all"},event_type:{type:"string",description:'事件类型正则过滤。例如: "view" 匹配页面 view 事件, "CLK" 匹配点击埋点'},filter:{type:"string",description:"正则过滤,匹配事件的 name 或 url 字段"},since:{type:"number",description:"从多久之前开始获取(秒)。例如: 60 表示获取最近 1 分钟内的事件"},after:{type:"string",description:"tab checkpoint 或上一次查询返回的 cursor,仅返回其后的埋点事件"},limit:{type:"number",description:"返回条数上限,默认 20",default:20},includeRaw:{type:"boolean",description:"是否返回完整 tracking URL、_raw 原始载荷和 _context 上下文;默认 false,仅返回解析后的精简字段",default:!1}}}},{name:"browser_get_logs",description:"获取指定标签页持续采集的 console API、未捕获异常和浏览器日志。无需打开 DevTools panel;不传 after 时返回最新 N 条,传 after 时从最早未读项开始分页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取;不传时使用当前活动标签页"},level:{type:"string",enum:["log","warn","error","info","all"],description:"日志级别过滤。log: 普通日志, warn: 警告, error: 错误, info: 信息, all: 所有级别。默认 all",default:"all"},since:{type:"number",description:"从多久之前开始获取日志(秒)。例如: 60 表示获取最近 1 分钟内的日志"},after:{type:"string",description:"tab checkpoint 或上一次查询返回的 cursor,仅返回其后的日志"},limit:{type:"number",description:"最大返回日志数量,默认 100;快照查询返回最新 N 条",default:100},filter:{type:"string",description:'过滤日志内容的正则表达式或字符串(可选)。支持正则表达式模式(不区分大小写),若正则无效则回退到字符串包含匹配。例如: "error|warning" 匹配包含 error 或 warning 的日志'}}}},{name:"browser_set_mock",description:"动态设置 API 接口的 Mock 数据,用于测试不同数据场景。修改后,浏览器中对该接口的所有请求都会返回 Mock 数据。适用于前端开发测试、边界情况验证、UI 状态测试等。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取;不传时使用当前活动标签页"},apiName:{type:"string",description:'API 名称或正则表达式模式。例如: "mtop.cart.query" 精确匹配, ".*\\.cart\\..*" 匹配所有购物车接口'},mockData:{type:["object","string"],description:'【方式一】直接设置完整 Mock 响应数据(JSON 对象)。传入后该接口将完全返回此数据,不再请求真实服务端。示例: {"data":{"result":{"list":[]}},"ret":["SUCCESS"]}。注意:mockData 和 fields 二选一,同时提供时优先使用 fields。大体积响应体可传文件引用字符串 "@/abs/resp.json"(从该文件读取,建议绝对路径)以减少上下文占用'},fields:{type:"array",description:"【方式二】基于真实响应修改指定字段。系统会先获取该接口的原始响应数据,然后按指定路径修改字段值。适合在真实数据基础上做微调",items:{type:"object",properties:{path:{type:"string",description:'字段路径,支持点号和数组索引。例如: "data.result.passengerList[0].name.text"'},value:{description:"要设置的值,可以是任意类型(字符串、数字、对象、数组等)"}},required:["path","value"]}},enabled:{type:"boolean",description:"是否启用 Mock。true: 启用 Mock, false: 禁用 Mock 恢复真实数据。默认 true",default:!0},duration:{type:"number",description:"完整响应时长(毫秒)。可选,mock 生效时的总耗时,绕过真实服务器精确控制(用于测试加载状态、超时等场景)"},conditions:{type:"object",additionalProperties:!0,description:"请求 query/body 字段的子集匹配规则;保留字段 $index 从 0 开始指定同一场景的调用顺序。相同 $index 再次设置会原地覆盖,超过最后一项后持续使用最后一项"},payloadFile:{type:"string",description:"从文件读取 mock 数据(JSON 格式)。当 mockData 很大时,可将完整 JSON 写入文件,通过此参数指定文件路径。文件内容会被解析为 mockData。注意:此参数与 mockData/fields 互斥,优先级最高"}},required:["apiName"]}},{name:"browser_get_mocks",description:"查看当前所有已设置的 Mock 配置,包括接口名称、是否启用、以及 Mock 数据内容。用于排查 Mock 是否生效、Mock 数据是否正确等问题。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID,从 browser_tab_list 获取;不传时使用当前活动标签页"},apiName:{type:"string",description:'过滤指定接口,支持正则表达式。例如: "mtop.cart.query" 或 ".*\\.cart\\..*"。不传则返回所有 Mock'}}}},{name:"browser_send_request",description:"通过浏览器发起 HTTP 代理请求,自动携带目标域名的 Cookie(使用当前浏览器登录态)。支持 GET/POST/PUT/DELETE/PATCH、multipart 文本字段和本地文件上传,适用于需要用户登录态的接口调试、数据爬取、接口测试等场景。",inputSchema:{type:"object",properties:{url:{type:"string",description:"目标请求 URL,必须是完整 URL(含 http:// 或 https://)"},method:{type:"string",enum:["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"],description:"HTTP 请求方法,默认 GET",default:"GET"},headers:{type:"object",description:"自定义请求头(键值对),会与自动生成的 Cookie 头合并",additionalProperties:{type:"string"}},params:{type:"object",description:"URL 查询参数(键值对),会追加到 URL 中",additionalProperties:{type:"string"}},body:{description:"请求体。传入对象时自动序列化为 JSON 并设置 Content-Type: application/json;传入字符串时原样发送"},formData:{type:"object",description:"multipart/form-data 文本字段。字段值支持 string、number、boolean;不能与 body 同时使用",additionalProperties:{anyOf:[{type:"string"},{type:"number"},{type:"boolean"}]}},files:{type:"array",description:"multipart 文件列表,最多 20 个且总计不超过 40 MiB。本地调用优先传绝对 filePath;远程调用可传 base64,并同时提供 filename,Base64 文件内容总计不超过 7 MiB",maxItems:20,items:{type:"object",properties:{fieldName:{type:"string",description:"multipart 字段名,例如 file"},filePath:{type:"string",description:"Mearl native-host 所在机器上的绝对文件路径"},base64:{type:"string",description:"文件内容的 Base64;与 filePath 二选一"},filename:{type:"string",description:"上传文件名;使用 base64 时必填"},contentType:{type:"string",description:"文件 MIME 类型;默认根据文件名推断"}},required:["fieldName"],oneOf:[{required:["filePath"]},{required:["base64","filename"]}]}},withCookies:{type:"boolean",description:"是否自动携带浏览器中该域名的 Cookie,默认 true",default:!0},responseType:{type:"string",enum:["json","text","auto"],description:'响应格式。auto: 自动检测(默认); json: 强制解析为 JSON; text: 返回原始文本。注意:auto 模式下若 Content-Type 为图片/音视频/PDF/压缩包等二进制类型,body 将以 base64 字符串返回,bodyType 为 "base64"',default:"auto"},timeout:{type:"number",description:"请求超时时间(毫秒),默认 30000(30 秒)",default:3e4}},required:["url"]}},{name:"browser_send_mtop_request",description:"在当前浏览器页面上下文中发起 mtop API 请求。自动处理签名计算(md5)、Cookie 中的 token 提取、时间戳生成等,无需手动构造签名。适用于:调试 mtop 接口、验证接口返回数据、测试不同参数组合等场景。注意:需要当前页面已登录(有对应的 Cookie),且 DevTools 面板已打开。",inputSchema:{type:"object",properties:{api:{type:"string",description:'mtop API 名称,例如: "mtop.trade.order.create"、"mtop.fliggy.flyrs.render"。以 "mopen." 开头的会使用 mopen 签名算法'},data:{description:'请求数据(JSON 对象),即 mtop 请求中的 data 参数。例如: {"itemId": "12345"}'},version:{type:"string",description:'API 版本号,默认 "1.0"',default:"1.0"},method:{type:"string",enum:["GET","POST"],description:"HTTP 请求方法,默认 GET。POST 时 data 参数放在请求体中",default:"GET"},appKey:{type:"string",description:'appKey,默认 "12574478"'},env:{type:"string",enum:["prod","pre"],description:"请求环境。prod: 生产(默认,h5api.m.taobao.com); pre: 预发(h5api.wapa.taobao.com)",default:"prod"},timeout:{type:"number",description:"请求超时时间(毫秒),默认 10000(10 秒)",default:1e4}},required:["api"]}},{name:"browser_set_rule",description:"添加 Chrome declarativeNetRequest 规则,用于拦截、重定向或修改请求。规则持久化保存,浏览器重启后仍生效。支持:重定向请求到另一地址、修改请求/响应头、阻止请求、升级到 HTTPS 等。适用于:本地开发时代理到本地服务、修改请求头调试、拦截特定请求等。",inputSchema:{type:"object",properties:{actionType:{type:"string",enum:["redirect","block","allow","upgradeScheme","modifyHeaders"],description:"规则类型。redirect: 重定向请求到另一地址; block: 阻止请求; allow: 允许请求; upgradeScheme: 升级到 HTTPS; modifyHeaders: 修改请求/响应头"},filter:{type:"string",description:'URL 匹配规则(正则表达式)。例如: "^https://h5api\\.m\\.taobao\\.com/.*" 匹配所有淘宝 h5api 请求'},redirectUrl:{type:"string",description:"【redirect 类型必填】重定向目标 URL。支持正则替换占位符 \\1 \\2 等(引用 filter 中的捕获组)"},requestHeaders:{type:"array",description:"【modifyHeaders 类型】要修改的请求头列表",items:{type:"object",properties:{header:{type:"string",description:'请求头名称,如 "x-custom-header"'},operation:{type:"string",enum:["set","append","remove"],description:"set: 设置/覆盖; append: 追加; remove: 删除"},value:{type:"string",description:"请求头值(remove 时可省略)"}},required:["header","operation"]}},responseHeaders:{type:"array",description:"【modifyHeaders 类型】要修改的响应头列表",items:{type:"object",properties:{header:{type:"string",description:"响应头名称"},operation:{type:"string",enum:["set","append","remove"],description:"set: 设置/覆盖; append: 追加; remove: 删除"},value:{type:"string",description:"响应头值(remove 时可省略)"}},required:["header","operation"]}},initiatorDomains:{type:"string",description:'发起请求的域名限制(逗号分隔)。只有从这些域名发起的请求才会匹配此规则。例如: "taobao.com,tmall.com"'},resourceTypes:{type:"array",description:"资源类型限制。不填则匹配所有类型",items:{type:"string",enum:["main_frame","sub_frame","script","stylesheet","image","xmlhttprequest","websocket","other"]}},priority:{type:"number",description:"规则优先级,数字越大优先级越高。多个规则匹配同一请求时,优先级高的生效。默认 1",default:1},description:{type:"string",description:"规则描述,便于识别规则用途"}},required:["actionType","filter"]}},{name:"browser_get_rules",description:"查看当前存储的全部请求规则(含用户在插件 Options 面板手动配置的)。返回规则总开关状态和规则列表,字段结构与 browser_set_rule 入参对齐,用于确认规则是否生效或排查请求被意外重定向/修改的问题。",inputSchema:{type:"object",properties:{}}},{name:"browser_page_screenshot",description:'获取指定浏览器标签页的视觉截图,以 Base64 编码返回。支持全页截图或指定 CSS 选择器截取单个元素(类似 DevTools "Capture node screenshot")。适用于视觉判断、Canvas、跨域 iframe、UI 排查和保存快照;常规页面动作后优先读取其内置观察的增量结果,不要固定在每次动作后截图。',inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:"CSS 选择器。提供后只截取该元素区域(会自动滚动元素到可见区域),不提供则截取整个页面"},format:{type:"string",enum:["png","jpeg"],description:"截图格式。png: PNG 格式(无损,默认); jpeg: JPEG 格式(有损压缩,体积更小)",default:"png"},quality:{type:"number",description:"JPEG 质量(仅 format 为 jpeg 时有效)。范围 0-100,默认 80。数值越高质量越好但文件越大",default:80}},required:["tabId"]}},{name:"browser_launch",description:"启动浏览器实例。默认使用本地独立 Chrome;传已注册的 Provider ID 时,把该 Provider 声明的创建参数放在 providerOptions。配对实例会直接返回 pairing URL。具体 Provider 用法可运行 mearl <providerId> 查看。",inputSchema:{type:"object",properties:{name:{type:"string",description:"本地实例名称;使用默认 local Provider 时必填"},provider:{type:"string",description:"浏览器提供方,默认 local;也可传已注册的外部 Provider ID"},providerOptions:{type:"object",additionalProperties:!0,description:"所选外部 Provider 声明的结构化创建参数"},headless:{type:"boolean",description:"本地 Provider 是否使用 headless=new,默认 true"},userAgentMode:{type:"string",enum:["default","desktop"],description:"本地 UA 模式:default 使用默认 UA;desktop 使用匹配本机 Chrome 的 UA",default:"default"},persistent:{type:"boolean",description:"本地实例关闭后是否保留独立 Profile,默认 false",default:!1},url:{type:"string",description:"新浏览器打开的初始 URL"},executablePath:{type:"string",description:"Chrome 可执行文件路径;省略时自动发现,也可用环境变量配置"},copyCookieDomains:{oneOf:[{type:"array",items:{type:"string"}},{type:"string",enum:["mearl-services"]}],description:"从控制浏览器复制 Cookie。传域名数组时复制指定域;传 mearl-services 时同步 Mearl 依赖平台登录态。保留 HttpOnly/Secure/SameSite/过期时间等属性;域名数组中的非内置域需先授权。"}},anyOf:[{required:["name"]},{required:["provider"]}]}},{name:"browser_close",description:"关闭一个 Provider 托管浏览器;持久化数据默认按 Provider 策略保留,deleteProfile=true 时一并删除。名称有歧义时使用完整 browserId。",inputSchema:{type:"object",properties:{browser:{type:"string",description:"browser_launch 返回的 browserId 或实例名称"},deleteProfile:{type:"boolean",description:"是否强制删除 Provider 持久化数据,默认 false",default:!1}},required:["browser"]}},{name:"browser_release",description:"仅在用户明确要求结束调试、退出接管或清理会话资源时调用,不作为普通任务收尾。它会释放 debugger/CDP 控制和会话级临时效果,后续浏览器操作可自动重新建立控制;Provider 实例的生命周期操作由 Browser Manager 处理。",inputSchema:{type:"object",properties:{}}},{name:"browser_tab_open",description:"打开或按 URL 规则复用标签页。默认新建并等待加载完成;reuse=prefer 可优先复用,reuse=require 可限制为只复用。响应的 opened/reused 可用于判断流程结束时是否应关闭该 Tab。",inputSchema:{type:"object",properties:{url:{type:"string",description:"要打开的页面 URL"},active:{type:"boolean",description:"是否激活目标标签页并恢复最小化窗口。默认 false(后台打开);响应通过 activation 返回实际可见性",default:!1},openerTabId:{type:"number",description:"来源标签页 ID。侧边栏对话继续任务时传入,用于把新开或复用的标签页关联到同一对话"},closeExisting:{type:"boolean",description:"打开前是否先关闭 Agent 受控的已有标签页。默认 false",default:!1},group:{type:"string",description:"把新标签页加入指定标题的标签页分组(同窗口同名分组存在则加入,否则新建)。仅扩展模式支持,CDP 模式忽略"},reuse:{type:"string",enum:["never","prefer","require"],description:"never 始终新建;prefer 匹配到则复用、否则新建;require 只允许复用。默认 never",default:"never"},match:{type:"object",description:"复用标签页时的 URL 匹配规则",properties:{urlPattern:{type:"string",description:"支持 * 的完整 URL glob;省略时精确匹配 url"},ignoreSearch:{type:"boolean",description:"匹配时是否忽略 URL query,默认 false"},ignoreHash:{type:"boolean",description:"匹配时是否忽略 URL hash,默认 false"},onMultiple:{type:"string",enum:["error","first"],description:"匹配多个 Tab 时默认报错;first 显式取第一个"}}},restoreFocusOnClose:{type:"boolean",description:"新建 active Tab 关闭后是否恢复原活动标签页,默认 false",default:!1},emulation:{type:"object",description:"开 tab 即进入移动端模拟态,等价于随后立即调用 browser_set_device_emulation,但在导航前生效。deviceShell=true 时首屏就在 iframe WebView 与设备系统外壳中渲染。字段规则一致(无 enabled/reload)。",properties:{preset:{type:"string",enum:[...BROWSER_DEVICE_PRESET_NAMES],description:"内置设备预设,一键提供 viewport/DPR/UA。当前机型在前,旧机型 ID 继续兼容;可与下面字段组合,显式字段覆盖预设值"},width:{type:"number",description:"视口宽度(覆盖 preset)"},height:{type:"number",description:"视口高度(覆盖 preset)"},deviceScaleFactor:{type:"number",description:"devicePixelRatio(覆盖 preset)"},scale:{type:"number",exclusiveMinimum:0,description:"画面视觉比例,不改变视口 CSS 尺寸或 devicePixelRatio;必须为有限正数,默认 1"},mobile:{type:"boolean",description:"是否启用移动渲染模式。默认从 preset 推断,无 preset 默认 true"},userAgent:{type:"string",description:"自定义 User-Agent(覆盖 preset)。无 preset 时必填"},orientation:{type:"string",enum:["portrait","landscape"],description:"横竖屏,landscape 会对调宽高。默认 portrait"},touch:{type:"boolean",description:"是否启用触摸事件并把鼠标事件转成 touch。默认从 preset 推断;无 preset 时跟随 mobile"},deviceShell:{type:"boolean",description:"是否使用 iframe WebView 并渲染顶部状态栏与底部操作区,默认 false"},splitScreen:{type:"boolean",description:"是否在横屏设备外壳中将首页与业务页分置左右 WebView;仅与 appProfile、deviceShell=true、orientation=landscape 同时生效,默认 false"}}},appProfile:{type:"string",enum:[...client.APP_PROFILE_NAMES],description:"开 tab 即注入 App 客户端环境与 JSBridge(等价于随后调用 browser_set_app_profile,但在首次导航前生效)。不创建根 iframe;需要设备外壳时同时传 emulation.deviceShell=true"},os:{type:"string",enum:["ios","android"],description:"与 appProfile 配合;容器系统,默认 ios"},bridgeConfig:{type:"object",description:"与 appProfile 配合;声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}},不执行配置脚本"}},required:["url"]}},{name:"browser_tab_close",description:"关闭指定的浏览器标签页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"要关闭的标签页 ID(从 tab_open 或 tab_list 获取)"}},required:["tabId"]}},{name:"browser_tab_list",description:"列出当前浏览器窗口中所有标签页的信息,包括 ID、URL、标题和是否活动。",inputSchema:{type:"object",properties:{}}},{name:"browser_page_click",description:"点击页面元素;selector、text、point 三种定位方式必须且只能提供一种。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:`原生 CSS 选择器(如 "[aria-label='提交']"、"#login-btn")或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e3",必须带 "@" 前缀)。注意字段名是 "selector" 而非 "ref"。不支持 :has-text/:visible 等 Playwright 扩展语法。与 text/point 互斥。`},text:{type:"string",description:'按可见文本(accessibility name)定位。例如 "退款明细"。匹配到多个时会报错并列出候选——可加 role 或 exact:true 收敛,或用 page_snapshot 拿 @ref。与 selector/point 互斥。'},point:{type:"object",description:"按视口坐标点击(CSS 像素,左上角为原点)。selector 和 text 都不适用时使用。与 selector/text 互斥。",properties:{x:{type:"number",description:"横坐标(CSS 像素)"},y:{type:"number",description:"纵坐标(CSS 像素)"}},required:["x","y"]},role:{type:"string",description:'配合 text 使用,按 AX role 过滤消歧(如 "button"、"link"、"heading"、"StaticText")'},exact:{type:"boolean",description:"配合 text 使用,默认 true 精确匹配;false 时按子串匹配",default:!0},scope:{type:"string",description:'配合 text 使用,把 AX 文本匹配限制在指定 CSS 元素或 snapshot ref(如 "@e12")子树内'},clickMode:{type:"string",enum:["auto","dom","mouse","touch"],description:"默认 auto:可见页使用匹配设备的可信输入,隐藏页使用 DOM;dom/mouse/touch 可强制指定派发方式",default:"auto"},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId"]}},{name:"browser_page_drag",description:"连续拖动页面元素或视口坐标,适用于轮播图、滑块、Canvas 手势和拖放。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},from:{description:"拖动起点:CSS/@eN selector,或 {x,y} 视口坐标(CSS 像素)",anyOf:[{type:"string"},{type:"object",properties:{x:{type:"number"},y:{type:"number"}},required:["x","y"]}]},to:{description:"拖动终点:CSS/@eN selector,或 {x,y} 视口坐标(CSS 像素)",anyOf:[{type:"string"},{type:"object",properties:{x:{type:"number"},y:{type:"number"}},required:["x","y"]}]},dragMode:{type:"string",enum:["auto","dom","mouse","touch"],description:"默认 auto:可见页使用匹配设备的可信输入,隐藏页使用 DOM;dom/mouse/touch 可强制指定派发方式",default:"auto"},durationMs:{type:"number",minimum:0,maximum:5e3,description:"拖动持续时间(毫秒),默认 400;内部自动分段移动",default:400},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","from","to"]}},{name:"browser_page_type",description:"向输入框填写文本,兼容 React 等框架的受控组件。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:'原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e6",必须带 "@" 前缀)。字段名是 "selector"。不支持 :has-text/:visible 等 Playwright 扩展。'},text:{type:"string",description:"要输入的文本内容"},clearFirst:{type:"boolean",description:"是否先清空输入框原有内容。默认 true",default:!0},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","selector","text"]}},{name:"browser_page_scroll",description:'按方向滚动页面或指定容器;页面根不可滚动时自动发现活动滚动区,containerPolicy="nearest" 可从子节点解析最近的可滚动祖先。',inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},direction:{type:"string",enum:["up","down","top","bottom"],description:"滚动方向"},distance:{type:"number",description:"滚动距离(像素),仅 up/down 方向有效。默认 600",default:600},selector:{type:"string",description:'目标滚动容器的原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e6",必须带 "@" 前缀);不传时滚动页面。'},containerPolicy:{type:"string",enum:["self","nearest"],description:"默认 self,要求 selector 本身可滚动;nearest 会在其不可滚动时使用最近的可滚动祖先"},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","direction"]}},{name:"browser_page_hover",description:"将鼠标悬停在页面元素上。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:'原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e1",必须带 "@" 前缀)。字段名是 "selector"。不支持 :has-text/:visible 等 Playwright 扩展。'},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","selector"]}},{name:"browser_page_eval",description:"在页面上下文中执行 JavaScript 表达式,作为结构化页面 action 无法表达时的补充。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},expression:{type:"string",description:"要执行的 JavaScript 表达式"},frameId:{type:"string",description:"目标 frame 的 CDP frameId。不传则在主 frame 中执行。可通过 browser_page_frames 获取"},awaitPromise:{type:"boolean",description:"是否等待表达式返回的 Promise,默认 true",default:!0},observe:{...OBSERVE_INPUT_SCHEMA,type:"object",description:"仅在表达式会修改页面且需要观察结果时显式传入;不传时轻量执行并直接返回结果"},diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","expression"]}},{name:"browser_page_inspect",description:"查询 DOM 元素数量、边框盒、计算样式、命中遮挡、溢出尺寸和最近滚动容器;也可读取 DevTools 当前选区或直接扫描全页。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:'原生 CSS、page_snapshot 返回的 ref(如 "@e8"),或 DevTools Elements 当前选区 "$0";全页溢出诊断时可省略'},filter:{type:"string",enum:["all","overflowing","horizontal-overflow","vertical-overflow","scrollable"],description:"结果过滤;省略 selector 时必须指定非 all 的过滤条件"},styles:{type:"array",items:{type:"string"},description:"要返回的计算样式属性;默认 display/position/box-sizing/overflow-x/overflow-y"},maxResults:{type:"number",minimum:1,maximum:100,description:"最多返回的明细数,默认 20;未触发 scanTruncated 时 count 为完整命中数"},includeOuterHTML:{type:"boolean",description:"是否返回 outerHTML(最多 3000 字符);$0 默认 true,其他目标默认 false"}},required:["tabId"]}},{name:"browser_page_snapshot",description:"获取带 @ref 的页面结构树;默认使用无障碍树,AX 信息缺失时可显式读取渲染 DOM。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},depth:{type:"number",description:"无障碍树的最大深度。默认 15,增大可获取更深层元素",default:15},mode:{type:"string",enum:["full","interactive","viewport","dom"],description:"full 为完整 AX 树;interactive 只保留当前视口内的 AX 语义控件,无控件时回退到 AX viewport;viewport 为当前可视 AX 树;dom 显式返回实际渲染文本、原生控件、显式 role 和高置信 clickable 节点。默认 full"},rootSelector:{type:"string",description:"只获取指定 CSS 元素的局部子树,可与 mode 组合;与 rootRef 互斥"},rootRef:{type:"string",description:'以已有 snapshot ref(如 "@e8")为根获取局部子树'},ancestorDepth:{type:"number",description:"rootRef 向上扩展的 DOM 祖先层数,默认 0,最大 20",minimum:0,maximum:20},query:{type:"object",description:"服务端按 name / role 过滤当前模式的树,只保留命中节点及祖先路径",properties:{text:{type:"string",description:"要匹配的 accessibility name"},role:{type:"string",description:"要匹配的 AX role"},exact:{type:"boolean",description:"text 默认精确匹配;false 时按子串匹配"}}},maxNodes:{type:"number",description:"最多输出节点数;超出时保留首尾。0 表示不限制"},maxChars:{type:"number",description:"最多输出字符数,默认 60000;超出时保留首尾。0 表示不限制"}},required:["tabId"]}},{name:"browser_page_press",description:"在页面中按下键盘按键或组合键。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},key:{type:"string",description:"按键名称。支持:Enter, Tab, Escape, Backspace, Delete, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, Home, End, PageUp, PageDown, Space"},modifiers:{type:"array",items:{type:"string"},description:'修饰键数组,如 ["Alt", "Shift", "Control", "Meta"]'},pressMode:{type:"string",enum:["auto","dom","keyboard"],description:"派发模式;auto 默认在隐藏页降级为 DOM 键盘事件"},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","key"]}},{name:"browser_page_wait",description:"独立等待接口:仅用于没有前置动作时等待指定时间、已知 selector 状态、可见文本或页面 condition。四种模式必须且只能提供一个;点击、输入后的异步稳定判断由页面交互工具内置的观察完成。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},time:{type:"number",description:"固定等待毫秒数,与 selector/text/condition 四选一"},selector:{type:"string",description:"CSS 选择器,与 time/text/condition 四选一"},state:{type:"string",enum:["attached","detached","visible","hidden"],description:"selector 的目标状态,默认 attached",default:"attached"},text:{type:"string",description:"等待页面出现的可见文本,与 time/selector/condition 四选一"},exact:{type:"boolean",description:"text 是否精确匹配,默认 false",default:!1},condition:{type:"string",description:"在页面主上下文轮询的 JavaScript 表达式,返回 truthy 时结束,支持 Promise;与 time/selector/text 四选一"},timeout:{type:"number",description:"等待超时时间(毫秒),默认 10000ms",default:1e4},interval:{type:"number",description:"selector/condition 的轮询间隔(毫秒),默认 200ms",default:200}},required:["tabId"]}},{name:"browser_page_navigate",description:'在指定标签页中导航到 URL、设置 refresh:true 重新加载,或用 history:"back"|"forward" 沿浏览历史移动。三种模式互斥,返回最终 URL 和标题。',inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},url:{type:"string",description:"要导航到的 URL;与 refresh/history 互斥"},refresh:{type:"boolean",description:"为 true 时直接重新加载当前页面;与 url/history 互斥",default:!1},history:{type:"string",enum:["back","forward"],description:"沿当前标签页浏览历史后退或前进;与 url/refresh 互斥"}},required:["tabId"]}},{name:"browser_page_upload",description:'向 <input type="file"> 元素上传一个或多个本地文件。',inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},selector:{type:"string",description:'原生 CSS 选择器,或 page_snapshot / 页面动作 observation 返回的 ref(如 "@e5",必须带 "@" 前缀),用于定位 <input type="file"> 元素。字段名是 "selector"。'},filePaths:{type:"array",items:{type:"string"},description:'要上传的本地文件路径数组,如 ["/Users/me/photo.jpg"]'},observe:OBSERVE_INPUT_SCHEMA,diagnostics:DIAGNOSTICS_INPUT_SCHEMA},required:["tabId","selector","filePaths"]}},{name:"browser_page_frames",description:"列出主 frame 和 iframe,返回可供 browser_page_eval 使用的 frameId。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"}},required:["tabId"]}},{name:"browser_set_device_emulation",description:"把目标标签页切换为移动端模拟态:视口尺寸 / DPR / UA / 触摸事件按指定设备生效,并可独立调整视觉比例。deviceShell=true 时把业务页放入 iframe WebView,并在外层渲染顶部状态栏与底部操作区;false/省略时保持纯 CDP 模拟。作用域仅限该 tab,启用后默认 reload,enabled=false 清除模拟与设备外壳。",inputSchema:{type:"object",properties:{enabled:{type:"boolean",description:"必填。true=启用模拟(按 preset/参数生效),false=清除模拟回到桌面态"},preset:{type:"string",enum:[...BROWSER_DEVICE_PRESET_NAMES],description:"内置设备预设,一键提供 viewport/DPR/UA。当前机型在前,旧机型 ID 继续兼容;可与下面的字段组合,显式字段会覆盖预设值"},width:{type:"number",description:"视口宽度(覆盖 preset)"},height:{type:"number",description:"视口高度(覆盖 preset)"},deviceScaleFactor:{type:"number",description:"devicePixelRatio(覆盖 preset)"},scale:{type:"number",exclusiveMinimum:0,description:"画面视觉比例,不改变视口 CSS 尺寸或 devicePixelRatio;必须为有限正数,默认 1"},mobile:{type:"boolean",description:"是否启用移动渲染模式(影响 hover/pointer media query、viewport meta 行为)。默认从 preset 推断,无 preset 默认 true"},userAgent:{type:"string",description:"自定义 User-Agent(覆盖 preset)"},orientation:{type:"string",enum:["portrait","landscape"],description:"横竖屏,landscape 会对调宽高。默认 portrait"},touch:{type:"boolean",description:"是否启用触摸事件并把鼠标事件转成 touch。默认从 preset 推断;无 preset 时跟随 mobile"},deviceShell:{type:"boolean",description:"是否使用 iframe WebView 并渲染顶部状态栏与底部操作区,默认 false"},splitScreen:{type:"boolean",description:"是否在横屏 App 容器中将首页与业务页分置左右 WebView;仅在当前已启用 App 档案、deviceShell=true、orientation=landscape 时生效,默认 false"},reload:{type:"boolean",description:"启用模拟后是否重载页面(让 JS 读到新的 navigator.userAgent / window.innerWidth)。默认 true"},tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"}},required:["tabId","enabled"]}},{name:"browser_set_app_profile",description:"设置目标标签页的 App 客户端 UA、环境变量、JSBridge 与桥协议,也可设置插件的 MTop 页面接口环境。传 emulation 时由同一个调用联动设备模拟与 iframe 系统外壳;省略 emulation 时不改变设备状态。",inputSchema:{type:"object",properties:{enabled:{type:"boolean",description:"必填。true=启用容器模拟,false=清除并还原设备模拟"},profile:{type:"string",enum:[...client.APP_PROFILE_NAMES],description:"容器档案名(enabled=true 时必填),决定 UA/桥对象/环境判断特征"},os:{type:"string",enum:["ios","android"],description:"容器系统,默认 ios"},appVersion:{type:"string",description:"覆盖档案默认 App 版本号"},deviceModel:{type:"string",description:"Android 机型名(拼入 UA 与 __DEVICE_MODEL__)"},bridgeConfig:{type:"object",description:"声明式覆盖桥方法,形如 {methods:{api:{behavior|response|noop,silent?}}};扩展本地同档案配置会先合并"},mtopEnv:{type:"string",enum:["default","prod","pre"],description:"可选 MTop 页面接口环境。default 关闭环境改写;省略时保持当前设置。扩展模式与插件设置页共享并全局生效,CDP 模式仅作用于目标 tab。"},emulation:{type:"object",description:"可选设备联动参数;字段覆盖档案推荐设备,空对象使用推荐设备,deviceShell 默认 true。省略时不设置或清除设备。",properties:{preset:{type:"string",enum:[...BROWSER_DEVICE_PRESET_NAMES]},width:{type:"number"},height:{type:"number"},deviceScaleFactor:{type:"number"},scale:{type:"number",exclusiveMinimum:0},mobile:{type:"boolean"},userAgent:{type:"string"},orientation:{type:"string",enum:["portrait","landscape"]},touch:{type:"boolean"},deviceShell:{type:"boolean",description:"是否使用根 iframe WebView 并显示系统栏;在 emulation 内默认 true"},splitScreen:{type:"boolean",description:"是否在横屏设备外壳中将首页与业务页分置左右 WebView;仅与 deviceShell=true、orientation=landscape 同时生效,默认 false"}}},reload:{type:"boolean",description:"应用/清除后是否重载页面,默认 true"},tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"}},required:["tabId","enabled"]}},{name:"browser_set_timezone",description:"覆盖目标标签页的时区,作用域仅限该 tab,立即影响 Date / Intl 等页面时间 API。timezone 使用 IANA 时区标识(如 Asia/Shanghai、America/New_York);传空字符串恢复浏览器默认时区。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},timezone:{type:"string",description:"IANA 时区标识;空字符串表示清除覆盖"}},required:["tabId","timezone"]}},{name:"browser_get_cookie",description:"从目标浏览器读取一个指定非分区 Cookie,用于验证页面分支、实验或当前账号标识。必须明确传 Cookie 名,不支持列举全部 Cookie;HttpOnly Cookie 会被拒绝,禁止读取认证 Token。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},name:{type:"string",description:"Cookie 名称"},url:{type:"string",description:"可选 Cookie 查询 URL;省略时使用当前标签页 URL"},domain:{type:"string",description:"可选精确域过滤,只允许 Cookie 查询 URL 的 host 或它的父域"},path:{type:"string",description:"可选精确 path 过滤"}},required:["tabId","name"]}},{name:"browser_set_cookie",description:"修改当前标签页使用的一个指定非分区 session Cookie。不枚举、不读取其它 Cookie;未传 domain 时只写当前 host,显式传域时只允许当前 host 或它的父域。",inputSchema:{type:"object",properties:{tabId:{type:"number",description:"目标标签页 ID(从 browser_tab_open 或 browser_tab_list 获取)"},name:{type:"string",description:"Cookie 名称"},value:{type:"string",description:"Cookie 值,可传空字符串;空字符串不会删除 Cookie"},domain:{type:"string",description:"Cookie 域,默认当前 host;只允许当前 host 或它的父域"},path:{type:"string",description:"Cookie path,默认 /"},reload:{type:"boolean",description:"设置后是否刷新当前页面,默认 false"}},required:["tabId","name","value"]}},{name:"browser_run_actions",description:"批量顺序执行多个无需中间判断的原子操作,适合 hover→click 等必须紧密连续的序列。步骤内的页面动作不带内置观察;遇到第一个失败步骤立即停止,且不能嵌套 run_actions。若下一步需要根据页面变化决定,优先逐步使用带观察的页面交互工具;不要用本工具固化「点击→等待→截图」循环。",inputSchema:{type:"object",properties:{actions:{type:"array",description:"要依次执行的 action 列表",items:{type:"object",properties:{action:{type:"string",description:"action 名称(不带 browser_ 前缀),如 page_hover、page_click;仅组合无需中间判断的步骤"},data:{type:"object",description:"该 action 的参数(与单独调用时相同)"}},required:["action"]}},tabId:{type:"number",description:"所有步骤共享的目标标签页 ID。步骤自身指定的 tabId 优先级更高"}},required:["tabId","actions"]}},{name:"browser_list",description:"列出所有浏览器。返回普通浏览器和 Provider 托管浏览器的 browserId、名称、类型、连接状态、稳定元数据及当前默认目标,但不返回带临时凭据的浏览器访问地址。只有 status=connected 的浏览器可用于后续操作。",inputSchema:{type:"object",properties:{}}},{name:"browser_select_browser",description:"选择后续所有浏览器操作的默认目标浏览器(有多个浏览器连接时)。传入 browser_list 返回且 status=connected 的 browserId 或名称即可锁定;传空字符串则清除锁定,回到自动模式(操作最近聚焦的浏览器)。",inputSchema:{type:"object",properties:{browser:{type:"string",description:"目标浏览器的 browserId / 名称;空字符串表示清除锁定、恢复自动选择"}},required:["browser"]}},{name:"browser_request_domain_permission",description:"申请访问指定域名的权限。调用后浏览器会弹出确认窗口让用户授权(90 秒超时),返回 granted 表示是否已获得授权。扩展模式下发送非内置域的 HTTP 请求(browser_send_request)前需先获得用户授权。",inputSchema:{type:"object",properties:{domain:{type:"string",description:"需要授权的域名,如 example.com"}},required:["domain"]}}];server.setRequestHandler(ListToolsRequestSchema,async()=>({tools})),server.setRequestHandler(CallToolRequestSchema,async request=>{let{arguments:args}=request.params,name=request.params.name==="browser_capture_checkpoint"?"browser_tab_checkpoint":request.params.name;try{if(name!==PLUGIN_INVOKE_TOOL_NAME&&!(name in MCP_TOOL_ACTIONS))throw new Error(`Unknown tool: ${name}`);let toolName=name,result;switch(toolName){case PLUGIN_INVOKE_TOOL_NAME:{result=await invokePluginTool(args,client.invokePlugin);break}case"browser_tab_checkpoint":{let{tabId}=args;result=await client.tabCheckpoint({tabId});break}case"browser_get_requests":{let{tabId,count=10,filter,since,after,includeBody=!0,includeHeaders=!1,maxBodySize=5e4,fields,keysOnly=!1,source}=args;result=await client.getRequests({tabId,count,filter,since,after,includeBody,includeHeaders,maxBodySize,fields,keysOnly,source});break}case"browser_get_events":{let{tabId,source="all",event_type,filter,since,after,limit=20,includeRaw=!1}=args;result=await client.getEvents({tabId,source,event_type,filter,since,after,limit,includeRaw});break}case"browser_get_logs":{let{tabId,level="all",since,after,limit=100,filter}=args;result=await client.getLogs({tabId,level,since,after,limit,filter});break}case"browser_set_mock":{let{payloadFile}=args,{tabId,apiName,mockData,fields,enabled,duration:duration3,conditions}=args;if(enabled=enabled??!0,payloadFile){if(!existsSync(payloadFile))throw new Error(`Payload file not found: ${payloadFile}`);let fileContent=readFileSync(payloadFile,"utf-8"),fileData=JSON.parse(fileContent);fileData.tabId!==void 0&&(tabId=fileData.tabId),fileData.apiName&&(apiName=fileData.apiName),fileData.mockData!==void 0&&(mockData=fileData.mockData),fileData.fields!==void 0&&(fields=fileData.fields),fileData.enabled!==void 0&&(enabled=fileData.enabled),fileData.duration!==void 0&&(duration3=fileData.duration),fileData.conditions!==void 0&&(conditions=fileData.conditions)}result=await client.setMock({tabId,apiName,mockData,fields,enabled,duration:duration3,conditions});break}case"browser_get_mocks":{let{tabId,apiName}=args;result=await client.getMocks({tabId,apiName});break}case"browser_send_request":{result=await client.sendRequest(args);break}case"browser_send_mtop_request":{let{api,data,version:version2,method,appKey,env,timeout}=args;result=await client.sendMtopRequest({api,data,version:version2,method,appKey,env,timeout});break}case"browser_set_rule":{result=await client.setRule(args);break}case"browser_get_rules":{result=await client.getRules();break}case"browser_page_screenshot":{let{format="png",quality=80,selector,tabId}=args;return result=await client.pageScreenshot({format,quality,selector,tabId}),{content:[{type:"image",data:result.data,mimeType:result.meta.format==="jpeg"?"image/jpeg":"image/png"},{type:"text",text:`Screenshot captured: ${result.meta.width}x${result.meta.height} ${result.meta.format.toUpperCase()} (${Math.round(result.meta.size/1024)}KB)
|
|
101
101
|
Page: ${result.meta.title}
|
|
102
102
|
URL: ${result.meta.url}`}]}}case"browser_launch":{result=await client.browserLaunch(args);break}case"browser_close":{result=await client.browserClose(args);break}case"browser_release":{result=await client.browserRelease();break}case"browser_tab_open":{let{url:url2,active=!1,openerTabId,closeExisting=!1,reuse="never",match,restoreFocusOnClose=!1,emulation,group}=args;result=await client.tabOpen({url:url2,active,openerTabId,closeExisting,reuse,match,restoreFocusOnClose,emulation,group});break}case"browser_tab_close":{let{tabId}=args;result=await client.tabClose({tabId});break}case"browser_tab_list":{result=await client.tabList();break}case"browser_page_click":{let{tabId,selector,text,point,role,exact,scope,clickMode,observe,diagnostics}=args;result=await client.pageClick({tabId,selector,text,point,role,exact,scope,clickMode,observe,diagnostics});break}case"browser_page_drag":{let{tabId,from,to,dragMode,durationMs,observe,diagnostics}=args;result=await client.pageDrag({tabId,from,to,dragMode,durationMs,observe,diagnostics});break}case"browser_page_type":{let{tabId,selector,text,clearFirst=!0,observe,diagnostics}=args;result=await client.pageType({tabId,selector,text,clearFirst,observe,diagnostics});break}case"browser_page_scroll":{let{tabId,direction,distance=600,selector,containerPolicy,observe,diagnostics}=args;result=await client.pageScroll({tabId,direction,distance,selector,containerPolicy,observe,diagnostics});break}case"browser_page_hover":{let{tabId,selector,observe,diagnostics}=args;result=await client.pageHover({tabId,selector,observe,diagnostics});break}case"browser_page_eval":{let{tabId,expression,frameId,awaitPromise=!0,observe,diagnostics}=args;result=await client.pageEval({tabId,expression,frameId,awaitPromise,observe,diagnostics});break}case"browser_page_inspect":{let{tabId,selector,filter,styles,maxResults,includeOuterHTML}=args;result=await client.pageInspect({tabId,selector,filter,styles,maxResults,includeOuterHTML});break}case"browser_page_snapshot":{let{tabId,depth=15,mode,rootSelector,rootRef,ancestorDepth,query,maxNodes,maxChars}=args;result=await client.pageSnapshot({tabId,depth,mode,rootSelector,rootRef,ancestorDepth,query,maxNodes,maxChars});break}case"browser_page_press":{let{tabId,key,modifiers,pressMode,observe,diagnostics}=args;result=await client.pagePress({tabId,key,modifiers,pressMode,observe,diagnostics});break}case"browser_page_wait":{let{tabId,time:time3,selector,state,text,exact,condition,timeout=1e4,interval=200}=args;result=await client.pageWait({tabId,time:time3,selector,state,text,exact,condition,timeout,interval});break}case"browser_page_navigate":{let{tabId,url:url2,refresh,history}=args;result=await client.pageNavigate({tabId,url:url2,refresh,history});break}case"browser_page_upload":{let{tabId,selector,filePaths,observe,diagnostics}=args;result=await client.pageUpload({tabId,selector,filePaths,observe,diagnostics});break}case"browser_page_frames":{let{tabId}=args;result=await client.pageFrames({tabId});break}case"browser_set_device_emulation":{result=await client.setDeviceEmulation(args);break}case"browser_set_app_profile":{result=await client.setAppProfile(args);break}case"browser_set_timezone":{result=await client.setTimezone(args);break}case"browser_get_cookie":{result=await client.getCookie(args);break}case"browser_set_cookie":{result=await client.setCookie(args);break}case"browser_run_actions":{let{actions,tabId}=args;if(result=await client.runActions({actions,tabId}),result?.results?.length>0){let screenshots=result.results.filter(r=>r.success&&r.action==="page_screenshot"&&r.data?.data);if(screenshots.length>0)return{content:[...screenshots.map(r=>({type:"image",data:r.data.data,mimeType:r.data.meta?.format==="jpeg"?"image/jpeg":"image/png"})),{type:"text",text:JSON.stringify({...result,results:result.results.map(r=>r.action==="page_screenshot"&&r.success?{...r,data:{meta:r.data?.meta}}:r)},null,2)}]}}break}case"browser_list":{result=await client.browserList();break}case"browser_select_browser":{result=await client.selectBrowser(args);break}case"browser_request_domain_permission":{let{domain:domain2}=args;result=await client.invoke("request_domain_permission",{domain:domain2});break}default:{let unhandledTool=toolName;throw new Error(`Unknown tool: ${unhandledTool}`)}}return{content:formatResponseWithSizeCheck(result,name,args)}}catch(error2){return log(`Error executing tool ${name}:`,error2),{content:[{type:"text",text:`Error: ${error2 instanceof Error?error2.message:String(error2)}`}],isError:!0}}});let transport=new StdioServerTransport;await server.connect(transport),log("MCP Server started and ready")}process.on("uncaughtException",error2=>{console.error("[MCP Server] Uncaught exception:",error2),process.exit(1)});process.on("unhandledRejection",error2=>{console.error("[MCP Server] Unhandled rejection:",error2),process.exit(1)});main().catch(error2=>{console.error("[MCP Server] Failed to start:",error2),process.exit(1)});
|
package/dist/pluginTools.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { PluginInvocation, PluginInvokeOptions } from '@mearl/client';
|
|
2
2
|
export type PluginInvoker = (name: string, invocation: PluginInvocation, options?: PluginInvokeOptions) => Promise<unknown>;
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function invokePluginTool(value: unknown, invoke: PluginInvoker): Promise<unknown>;
|
package/dist/pluginTools.js
CHANGED
|
@@ -9,7 +9,7 @@ function requiredString(value, name) {
|
|
|
9
9
|
throw new Error(`${name} must be a non-empty string`);
|
|
10
10
|
return result;
|
|
11
11
|
}
|
|
12
|
-
export async function
|
|
12
|
+
export async function invokePluginTool(value, invoke) {
|
|
13
13
|
const input = asRecord(value);
|
|
14
14
|
if (!input)
|
|
15
15
|
throw new Error('plugin arguments must be an object');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/mcp-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.0",
|
|
4
4
|
"description": "MCP Server for Mearl - enables AI to interact with Chrome browser requests and logs",
|
|
5
5
|
"mcpName": "io.github.F-loat/mearl",
|
|
6
6
|
"type": "module",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"commander": "^15.0.0",
|
|
36
36
|
"prompts": "^2.4.2",
|
|
37
|
-
"@mearl/
|
|
38
|
-
"@mearl/
|
|
37
|
+
"@mearl/client": "2.19.0",
|
|
38
|
+
"@mearl/native-host": "2.19.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@modelcontextprotocol/sdk": "^1.0.4",
|