feat(wecom): 企微 API 插件增加 MCP Streamable HTTP 端点
与 REST/OpenAPI 并存,按实例权限自动 tools/list,免手填工具。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
import { WECOM_PLUGIN_MCP_TOOL_META, type WecomPluginMcpToolName } from '@dukang/shared-types';
|
||||
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { z } from 'zod';
|
||||
import { wecomPluginMcpErrorText, wecomPluginQueryArg } from './wecom-plugin.util';
|
||||
import type { WecomPluginQueryService } from './wecom-plugin-query.service';
|
||||
import type { WecomPluginRuntime } from './wecom-plugin.types';
|
||||
|
||||
const q = (description: string) => z.string().describe(description);
|
||||
const page = z.number().int().min(1).optional().describe('页码,默认 1');
|
||||
const pageSize = z.number().int().min(1).max(10).optional().describe('每页条数,默认 5,最大 10');
|
||||
const from = z.string().optional().describe('起始日期 YYYY-MM-DD 或 ISO');
|
||||
const to = z.string().optional().describe('结束日期 YYYY-MM-DD 或 ISO(含当天)');
|
||||
const auditStatus = z
|
||||
.enum(['PENDING', 'APPROVED', 'REJECTED'])
|
||||
.optional()
|
||||
.describe('审核状态,默认 PENDING');
|
||||
|
||||
export type WecomPluginMcpToolContext = {
|
||||
query: WecomPluginQueryService;
|
||||
plugin: WecomPluginRuntime;
|
||||
wecomUserId: string;
|
||||
};
|
||||
|
||||
async function jsonResult(run: () => Promise<unknown>): Promise<CallToolResult> {
|
||||
try {
|
||||
const data = await run();
|
||||
return { content: [{ type: 'text', text: JSON.stringify(data) }] };
|
||||
} catch (e) {
|
||||
return { content: [{ type: 'text', text: wecomPluginMcpErrorText(e) }], isError: true };
|
||||
}
|
||||
}
|
||||
|
||||
type ToolDef = {
|
||||
name: WecomPluginMcpToolName;
|
||||
description: string;
|
||||
inputSchema: Record<string, z.ZodTypeAny>;
|
||||
invoke: (ctx: WecomPluginMcpToolContext, args: Record<string, unknown>) => Promise<CallToolResult>;
|
||||
};
|
||||
|
||||
function str(args: Record<string, unknown>, key: string): string | undefined {
|
||||
return wecomPluginQueryArg(args[key] as string | number | undefined);
|
||||
}
|
||||
|
||||
export const WECOM_PLUGIN_MCP_TOOL_DEFS: ToolDef[] = [
|
||||
{
|
||||
name: 'query_orders',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_orders.description,
|
||||
inputSchema: { q: q('订单号,如 DK20260903xxxx'), page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() => ctx.query.queryOrders(ctx.plugin, ctx.wecomUserId, str(args, 'q'), str(args, 'page'), str(args, 'pageSize'))),
|
||||
},
|
||||
{
|
||||
name: 'query_users',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_users.description,
|
||||
inputSchema: { q: q('用户号或 11 位手机号'), page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() => ctx.query.queryUsers(ctx.plugin, ctx.wecomUserId, str(args, 'q'), str(args, 'page'), str(args, 'pageSize'))),
|
||||
},
|
||||
{
|
||||
name: 'query_stores',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_stores.description,
|
||||
inputSchema: { q: q('门店名称关键词'), page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() => ctx.query.queryStores(ctx.plugin, ctx.wecomUserId, str(args, 'q'), str(args, 'page'), str(args, 'pageSize'))),
|
||||
},
|
||||
{
|
||||
name: 'query_redeems',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_redeems.description,
|
||||
inputSchema: { q: q('核销单号或门店名'), page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() => ctx.query.queryRedeems(ctx.plugin, ctx.wecomUserId, str(args, 'q'), str(args, 'page'), str(args, 'pageSize'))),
|
||||
},
|
||||
{
|
||||
name: 'query_promo_codes',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_promo_codes.description,
|
||||
inputSchema: { q: q('推广码或名称'), page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() =>
|
||||
ctx.query.queryPromoCodes(ctx.plugin, ctx.wecomUserId, str(args, 'q'), str(args, 'page'), str(args, 'pageSize')),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'query_promo_code_stats',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_promo_code_stats.description,
|
||||
inputSchema: { code: q('推广码 code') },
|
||||
invoke: (ctx, args) => jsonResult(() => ctx.query.queryPromoCodeStats(ctx.plugin, ctx.wecomUserId, str(args, 'code'))),
|
||||
},
|
||||
{
|
||||
name: 'query_metrics',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_metrics.description,
|
||||
inputSchema: {
|
||||
kind: z.enum(['today', 'daily', 'weekly', 'monthly']).optional().describe('默认 today'),
|
||||
},
|
||||
invoke: (ctx, args) => jsonResult(() => ctx.query.queryMetrics(ctx.plugin, ctx.wecomUserId, str(args, 'kind'))),
|
||||
},
|
||||
{
|
||||
name: 'query_store_audits',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_store_audits.description,
|
||||
inputSchema: { q: z.string().optional().describe('门店名称'), status: auditStatus, page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() =>
|
||||
ctx.query.queryStoreAudits(
|
||||
ctx.plugin,
|
||||
ctx.wecomUserId,
|
||||
str(args, 'q'),
|
||||
str(args, 'status'),
|
||||
str(args, 'page'),
|
||||
str(args, 'pageSize'),
|
||||
),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'query_store_info_audits',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_store_info_audits.description,
|
||||
inputSchema: { status: auditStatus, page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() =>
|
||||
ctx.query.queryStoreInfoAudits(ctx.plugin, ctx.wecomUserId, str(args, 'status'), str(args, 'page'), str(args, 'pageSize')),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'query_store_info_audit_detail',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_store_info_audit_detail.description,
|
||||
inputSchema: { id: q('信息变更审核 ID') },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() => ctx.query.queryStoreInfoAuditDetail(ctx.plugin, ctx.wecomUserId, str(args, 'id') ?? '')),
|
||||
},
|
||||
{
|
||||
name: 'query_store_package_audits',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_store_package_audits.description,
|
||||
inputSchema: { status: auditStatus, page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() =>
|
||||
ctx.query.queryStorePackageAudits(ctx.plugin, ctx.wecomUserId, str(args, 'status'), str(args, 'page'), str(args, 'pageSize')),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'query_store_package_audit_detail',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_store_package_audit_detail.description,
|
||||
inputSchema: { id: q('套餐审核 ID') },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() => ctx.query.queryStorePackageAuditDetail(ctx.plugin, ctx.wecomUserId, str(args, 'id') ?? '')),
|
||||
},
|
||||
{
|
||||
name: 'query_partners',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_partners.description,
|
||||
inputSchema: { q: q('合伙人关键词'), page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() =>
|
||||
ctx.query.queryPartners(ctx.plugin, ctx.wecomUserId, str(args, 'q'), str(args, 'page'), str(args, 'pageSize')),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'query_partner_users',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_partner_users.description,
|
||||
inputSchema: { partnerId: q('合伙人 ID'), from, to, page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() =>
|
||||
ctx.query.queryPartnerUsers(
|
||||
ctx.plugin,
|
||||
ctx.wecomUserId,
|
||||
str(args, 'partnerId') ?? '',
|
||||
str(args, 'from'),
|
||||
str(args, 'to'),
|
||||
str(args, 'page'),
|
||||
str(args, 'pageSize'),
|
||||
),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'query_partner_stores',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_partner_stores.description,
|
||||
inputSchema: { partnerId: q('合伙人 ID'), from, to, page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() =>
|
||||
ctx.query.queryPartnerStores(
|
||||
ctx.plugin,
|
||||
ctx.wecomUserId,
|
||||
str(args, 'partnerId') ?? '',
|
||||
str(args, 'from'),
|
||||
str(args, 'to'),
|
||||
str(args, 'page'),
|
||||
str(args, 'pageSize'),
|
||||
),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'query_partner_orders',
|
||||
description: WECOM_PLUGIN_MCP_TOOL_META.query_partner_orders.description,
|
||||
inputSchema: { partnerId: q('合伙人 ID'), from, to, page, pageSize },
|
||||
invoke: (ctx, args) =>
|
||||
jsonResult(() =>
|
||||
ctx.query.queryPartnerOrders(
|
||||
ctx.plugin,
|
||||
ctx.wecomUserId,
|
||||
str(args, 'partnerId') ?? '',
|
||||
str(args, 'from'),
|
||||
str(args, 'to'),
|
||||
str(args, 'page'),
|
||||
str(args, 'pageSize'),
|
||||
),
|
||||
),
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user