molecule-core/mcp-server/src/tools/approvals.ts
Hongming Wang 1512e7ce62 refactor(mcp-server): split 1697-line index.ts into per-domain modules
Pure mechanical split, no behavior changes. Pulls the 70+ tool handlers
out of one monolith into api.ts (PLATFORM_URL + apiCall) plus 12
tools/*.ts files grouped by domain (workspaces, agents, secrets, files,
memory, plugins, channels, delegation, schedules, approvals, discovery,
remote_agents). Each module exports its handlers and a
registerXxxTools(srv) function; createServer() wires them up.

index.ts drops from 1697 → 89 lines. Largest new file is 183 lines.
All handlers still re-exported from index.ts so existing tests that
import them via "../index.js" keep working. Build clean; jest results
unchanged from pre-refactor baseline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:27:04 -07:00

76 lines
2.3 KiB
TypeScript

import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { apiCall } from "../api.js";
export async function handleListPendingApprovals() {
const data = await apiCall("GET", "/approvals/pending");
return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] };
}
export async function handleDecideApproval(params: {
workspace_id: string;
approval_id: string;
decision: "approved" | "denied";
}) {
const { workspace_id, approval_id, decision } = params;
const data = await apiCall(
"POST",
`/workspaces/${workspace_id}/approvals/${approval_id}/decide`,
{ decision, decided_by: "mcp-client" }
);
return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] };
}
export async function handleCreateApproval(params: {
workspace_id: string;
action: string;
reason?: string;
}) {
const { workspace_id, action, reason } = params;
const data = await apiCall("POST", `/workspaces/${workspace_id}/approvals`, { action, reason });
return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] };
}
export async function handleGetWorkspaceApprovals(params: { workspace_id: string }) {
const data = await apiCall("GET", `/workspaces/${params.workspace_id}/approvals`);
return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] };
}
export function registerApprovalTools(srv: McpServer) {
srv.tool(
"list_pending_approvals",
"List all pending approval requests across workspaces",
{},
handleListPendingApprovals
);
srv.tool(
"decide_approval",
"Approve or deny a pending approval request",
{
workspace_id: z.string().describe("Workspace ID"),
approval_id: z.string().describe("Approval ID"),
decision: z.enum(["approved", "denied"]).describe("Decision"),
},
handleDecideApproval
);
srv.tool(
"create_approval",
"Create an approval request for a workspace",
{
workspace_id: z.string(),
action: z.string().describe("What needs approval"),
reason: z.string().optional().describe("Why it's needed"),
},
handleCreateApproval
);
srv.tool(
"get_workspace_approvals",
"List approval requests for a specific workspace",
{ workspace_id: z.string() },
handleGetWorkspaceApprovals
);
}