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>
76 lines
2.3 KiB
TypeScript
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
|
|
);
|
|
}
|