Skip to main content
Glama

whistle-mcp

index.ts12.6 kB
import { FastMCP } from "fastmcp"; import { z } from "zod"; import { WhistleClient } from "./WhistleClient.js"; import minimist from "minimist"; // 解析命令行参数 const argv = minimist(process.argv.slice(2)); const host = argv.host || "localhost"; // 默认为localhost const port = argv.port ? parseInt(argv.port) : 8899; // 默认为8899 // 创建FastMCP服务器 const server = new FastMCP({ name: "Whistle MCP 服务", version: "1.0.5", }); // 实例化whistle客户端 const whistleClient = new WhistleClient(host, port); // 统一响应格式的包装函数 function formatResponse(data: any) { return { content: [ { type: "text" as const, text: JSON.stringify(data), }, ], }; } // 规则管理相关工具 server.addTool({ name: "getRules", description: "获取所有规则&分组", parameters: z.object({}), execute: async () => { const rules = await whistleClient.getRules(); return formatResponse(rules); }, }); server.addTool({ name: "createRule", description: "创建新规则", parameters: z.object({ name: z.string().describe("规则名称"), }), execute: async (args) => { const result = await whistleClient.createRule(args.name); return formatResponse(result); }, }); server.addTool({ name: "updateRule", description: "更新规则内容", parameters: z.object({ ruleName: z.string().describe("规则名称"), ruleValue: z.string().describe("规则内容"), }), execute: async (args) => { const { ruleName, ruleValue } = args; const result = await whistleClient.updateRule(ruleName, ruleValue); return formatResponse(result); }, }); server.addTool({ name: "renameRule", description: "重命名规则", parameters: z.object({ ruleName: z.string().describe("规则现有名称"), newName: z.string().describe("规则的新名称"), }), execute: async (args) => { const result = await whistleClient.renameRule(args.ruleName, args.newName); return formatResponse(result); }, }); server.addTool({ name: "deleteRule", description: "删除规则", parameters: z.object({ ruleName: z.string().describe("要删除的规则名称"), }), execute: async (args) => { const result = await whistleClient.deleteRule(args.ruleName); return formatResponse(result); }, }); server.addTool({ name: "enableRule", description: "启用规则", parameters: z.object({ ruleName: z.string().describe("规则名称"), }), execute: async (args) => { const result = await whistleClient.selectRule(args.ruleName); return formatResponse(result); }, }); server.addTool({ name: "disableRule", description: "禁用规则", parameters: z.object({ ruleName: z.string().describe("规则名称"), }), execute: async (args) => { const result = await whistleClient.unselectRule(args.ruleName); return formatResponse(result); }, }); // 分组管理相关工具 server.addTool({ name: "createGroup", description: "创建新分组", parameters: z.object({ name: z.string().describe("分组名称"), }), execute: async (args) => { const result = await whistleClient.createGroup(args.name); return formatResponse(result); }, }); server.addTool({ name: "renameGroup", description: "重命名分组", parameters: z.object({ groupName: z.string().describe("分组的现有名称"), newName: z.string().describe("分组的新名称"), }), execute: async (args) => { const result = await whistleClient.renameGroup( args.groupName, args.newName ); return formatResponse(result); }, }); server.addTool({ name: "deleteGroup", description: "删除分组", parameters: z.object({ groupName: z.string().describe("分组名称"), }), execute: async (args) => { const result = await whistleClient.deleteGroup(args.groupName); return formatResponse(result); }, }); server.addTool({ name: "addRuleToGroup", description: "将规则添加到分组", parameters: z.object({ groupName: z.string().describe("分组名称"), ruleName: z.string().describe("要添加的规则名称"), }), execute: async (args) => { const result = await whistleClient.moveRuleToGroup( args.ruleName, args.groupName ); return formatResponse(result); }, }); server.addTool({ name: "removeRuleFromGroup", description: "将规则移出分组", parameters: z.object({ ruleName: z.string().describe("规则名称"), }), execute: async (args) => { const result = await whistleClient.moveRuleOutOfGroup(args.ruleName); return formatResponse(result); }, }); server.addTool({ name: "getAllValues", description: "获取所有规则的值", parameters: z.object({}), execute: async () => { const rules = await whistleClient.getAllValues(); return formatResponse(rules); }, }); server.addTool({ name: "createValuesGroup", description: "创建新的值分组", parameters: z.object({ name: z.string().describe("分组名称"), }), execute: async (args) => { const result = await whistleClient.createValueGroup(args.name); return formatResponse(result); }, }); server.addTool({ name: "createValue", description: "创建新的值", parameters: z.object({ name: z.string().describe("值名称"), }), execute: async (args) => { const result = await whistleClient.createValue(args.name); return formatResponse(result); }, }); server.addTool({ name: "updateValue", description: "更新值内容", parameters: z.object({ name: z.string().describe("值名称"), value: z.string().describe("新值内容"), }), execute: async (args) => { const result = await whistleClient.updateValue(args.name, args.value); return formatResponse(result); }, }); server.addTool({ name: "renameValue", description: "重命名值", parameters: z.object({ name: z.string().describe("值现有名称"), newName: z.string().describe("值的新名称"), }), execute: async (args) => { const result = await whistleClient.renameValue(args.name, args.newName); return formatResponse(result); }, }); server.addTool({ name: "renameValueGroup", description: "重命名值分组", parameters: z.object({ groupName: z.string().describe("分组现有名称"), newName: z.string().describe("分组的新名称"), }), execute: async (args) => { const result = await whistleClient.renameValueGroup( args.groupName, args.newName ); return formatResponse(result); }, }); server.addTool({ name: "deleteValue", description: "删除值", parameters: z.object({ name: z.string().describe("值名称"), }), execute: async (args) => { const result = await whistleClient.deleteValue(args.name); return formatResponse(result); }, }); server.addTool({ name: "deleteValueGroup", description: "删除值分组", parameters: z.object({ groupName: z.string().describe("分组名称"), }), execute: async (args) => { const result = await whistleClient.deleteValueGroup(args.groupName); return formatResponse(result); }, }); server.addTool({ name: "addValueToGroup", description: "将值添加到分组", parameters: z.object({ groupName: z.string().describe("分组名称"), valueName: z.string().describe("要添加的值名称"), }), execute: async (args) => { const result = await whistleClient.moveValueToGroup( args.valueName, args.groupName ); return formatResponse(result); }, }); server.addTool({ name: "removeValueFromGroup", description: "将值移出分组", parameters: z.object({ valueName: z.string().describe("值名称"), }), execute: async (args) => { const result = await whistleClient.moveValueOutOfGroup(args.valueName); return formatResponse(result); }, }); // 代理控制相关工具 server.addTool({ name: "getWhistleStatus", description: "获取whistle服务器的当前状态", parameters: z.object({}), execute: async () => { const status = await whistleClient.getStatus(); return formatResponse(status); }, }); server.addTool({ name: "toggleProxy", description: "启用或禁用whistle代理", parameters: z.object({ enabled: z.boolean().describe("是否启用代理"), }), execute: async (args) => { const result = await whistleClient.toggleProxy(args.enabled); return formatResponse(result); }, }); server.addTool({ name: "toggleHttpInterception", description: "启用或禁用HTTP拦截", parameters: z.object({ enabled: z.boolean().describe("是否启用HTTP拦截"), }), execute: async (args) => { const result = await whistleClient.toggleHttpsInterception(args.enabled); return formatResponse(result); }, }); server.addTool({ name: "toggleHttpsInterception", description: "启用或禁用HTTPS拦截", parameters: z.object({ enabled: z.boolean().describe("是否启用HTTPS拦截"), }), execute: async (args) => { const result = await whistleClient.toggleHttpsInterception(args.enabled); return formatResponse(result); }, }); server.addTool({ name: "toggleHttp2", description: "启用或禁用HTTP/2", parameters: z.object({ enabled: z.boolean().describe("是否启用HTTP/2"), }), execute: async (args) => { const result = await whistleClient.toggleHttp2(args.enabled); return formatResponse(result); }, }); server.addTool({ name: "toggleMultiRuleMode", description: "启用或禁用多规则模式", parameters: z.object({ enabled: z.boolean().describe("是否启用多规则模式"), }), execute: async (args) => { const result = await whistleClient.toggleMultiRuleMode(args.enabled); return formatResponse(result); }, }); // 请求拦截与重放工具 server.addTool({ name: "getInterceptInfo", description: "获取URL的拦截信息(请求/响应皆以base64编码)", parameters: z.object({ url: z.string().optional().describe("要检查拦截信息的URL (支持正则表达式)"), startTime: z.string().optional().describe("开始时间ms(可选)"), count: z.number().optional().describe("请求数量(可选)"), }), execute: async (args) => { const { url = '', startTime = (Date.now() - 1000).toString(), count } = args; const result = await whistleClient.getInterceptInfo({ startTime, count }); const filteredResult = Object.values(result.data).filter((item: any) => { if (url) { try { const regex = new RegExp(url); return Array.isArray(item.url) ? item.url.some((u: string) => regex.test(u)) : regex.test(item.url); } catch (e) { // 正则表达式无效时,回退到简单的字符串包含检查 return Array.isArray(item.url) ? item.url.some((u: string | string[]) => u.includes(url)) : item.url.includes(url); } } return true; }); return formatResponse(filteredResult); }, }); server.addTool({ name: "replayRequest", description: "在whistle中重放捕获的请求(本接口请求后不会直接返回结果, 需要使用getInterceptInfo接口获取结果)", parameters: z.object({ url: z.string().describe("请求URL"), method: z.string().optional().describe("请求方法,默认为GET"), headers: z.string().optional().describe("请求头,可以是对象或字符串"), body: z.string().optional().describe("请求体,可以是字符串或对象"), useH2: z.boolean().optional().describe("是否使用HTTP/2") }), execute: async (args) => { const result = await whistleClient.replayRequest(args); return formatResponse(result); }, }); /** * 控制所有规则的启用状态 */ server.addTool({ name: "setAllRulesState", description: "控制所有规则的启用状态(启用/禁用)", parameters: z.object({ disabled: z .boolean() .describe("true表示禁用所有规则,false表示启用所有规则"), }), execute: async (args) => { const result = await whistleClient.disableAllRules(args.disabled); return formatResponse(result); }, }); /** * 返回当前本地的时间戳 */ server.addTool({ name: "getCurrentTimestamp", description: "获取当前本地时间戳", parameters: z.object({}), execute: async () => { const timestamp = Date.now(); return formatResponse({ timestamp }); }, }); // 启动服务器 server.start({ transportType: "stdio", });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/7gugu/whistle-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server