aidocx-mcp-server 0.1.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.
@@ -0,0 +1,11 @@
1
+ import type { AiDocxConfig } from "./config.js";
2
+ export declare class AiDocxClient {
3
+ private config;
4
+ constructor(config: AiDocxConfig);
5
+ private get headers();
6
+ get appUrl(): string;
7
+ private url;
8
+ get<T = any>(path: string, params?: Record<string, string>): Promise<T>;
9
+ post<T = any>(path: string, body: Record<string, any>): Promise<T>;
10
+ delete<T = any>(path: string): Promise<T>;
11
+ }
@@ -0,0 +1,57 @@
1
+ export class AiDocxClient {
2
+ config;
3
+ constructor(config) {
4
+ this.config = config;
5
+ }
6
+ get headers() {
7
+ return {
8
+ "Content-Type": "application/json",
9
+ "X-API-Key": this.config.apiKey,
10
+ "X-API-Secret": this.config.apiSecret,
11
+ };
12
+ }
13
+ get appUrl() {
14
+ return this.config.appUrl;
15
+ }
16
+ url(path) {
17
+ return `${this.config.apiUrl}/api${path}`;
18
+ }
19
+ async get(path, params) {
20
+ const url = new URL(this.url(path));
21
+ if (params) {
22
+ for (const [k, v] of Object.entries(params)) {
23
+ if (v !== undefined && v !== "")
24
+ url.searchParams.set(k, v);
25
+ }
26
+ }
27
+ const res = await fetch(url.toString(), { headers: this.headers });
28
+ if (!res.ok) {
29
+ const body = await res.text();
30
+ throw new Error(`API ${res.status}: ${body}`);
31
+ }
32
+ return res.json();
33
+ }
34
+ async post(path, body) {
35
+ const res = await fetch(this.url(path), {
36
+ method: "POST",
37
+ headers: this.headers,
38
+ body: JSON.stringify(body),
39
+ });
40
+ if (!res.ok) {
41
+ const text = await res.text();
42
+ throw new Error(`API ${res.status}: ${text}`);
43
+ }
44
+ return res.json();
45
+ }
46
+ async delete(path) {
47
+ const res = await fetch(this.url(path), {
48
+ method: "DELETE",
49
+ headers: this.headers,
50
+ });
51
+ if (!res.ok) {
52
+ const text = await res.text();
53
+ throw new Error(`API ${res.status}: ${text}`);
54
+ }
55
+ return res.json();
56
+ }
57
+ }
@@ -0,0 +1,7 @@
1
+ export interface AiDocxConfig {
2
+ apiKey: string;
3
+ apiSecret: string;
4
+ apiUrl: string;
5
+ appUrl: string;
6
+ }
7
+ export declare function loadConfig(): AiDocxConfig;
@@ -0,0 +1,12 @@
1
+ export function loadConfig() {
2
+ const apiKey = process.env.AIDOCX_API_KEY;
3
+ const apiSecret = process.env.AIDOCX_API_SECRET;
4
+ const apiUrl = process.env.AIDOCX_API_URL || "https://api.aidocx.ai";
5
+ const appUrl = process.env.AIDOCX_APP_URL || "https://app.aidocx.ai";
6
+ if (!apiKey || !apiSecret) {
7
+ console.error("[AiDocX MCP] Missing AIDOCX_API_KEY or AIDOCX_API_SECRET.\n" +
8
+ "Generate an API key at https://app.aidocx.ai/settings → API Keys.");
9
+ process.exit(1);
10
+ }
11
+ return { apiKey, apiSecret, apiUrl, appUrl };
12
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { loadConfig } from "./config.js";
5
+ import { AiDocxClient } from "./api-client.js";
6
+ import { register as registerCreateContractHtml } from "./tools/create-contract-html.js";
7
+ import { register as registerUploadContract } from "./tools/upload-contract.js";
8
+ import { register as registerListContracts } from "./tools/list-contracts.js";
9
+ import { register as registerGetContract } from "./tools/get-contract.js";
10
+ import { register as registerListFolders } from "./tools/list-folders.js";
11
+ import { register as registerCreateFolder } from "./tools/create-folder.js";
12
+ async function main() {
13
+ const config = loadConfig();
14
+ const client = new AiDocxClient(config);
15
+ const server = new McpServer({
16
+ name: "aidocx",
17
+ version: "0.1.0",
18
+ });
19
+ registerCreateContractHtml(server, client);
20
+ registerUploadContract(server, client);
21
+ registerListContracts(server, client);
22
+ registerGetContract(server, client);
23
+ registerListFolders(server, client);
24
+ registerCreateFolder(server, client);
25
+ const transport = new StdioServerTransport();
26
+ await server.connect(transport);
27
+ console.error("[AiDocX MCP] Server running on stdio");
28
+ }
29
+ main().catch((error) => {
30
+ console.error("[AiDocX MCP] Fatal:", error);
31
+ process.exit(1);
32
+ });
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { AiDocxClient } from "../api-client.js";
3
+ export declare function register(server: McpServer, client: AiDocxClient): void;
@@ -0,0 +1,48 @@
1
+ import { z } from "zod";
2
+ export function register(server, client) {
3
+ // @ts-expect-error -- MCP SDK generic recursion with zod v3.25+ optional()
4
+ server.registerTool("create_contract_from_html", {
5
+ description: "Create a new contract in AiDocX from HTML content. The HTML is rendered to a PDF " +
6
+ "using Noto Sans KR font and Tailwind CSS, then stored in document management. " +
7
+ "A4 page size with 2cm margins.\n\n" +
8
+ "IMPORTANT: Before calling this tool, you MUST confirm the following with the user:\n" +
9
+ "1. Contract type (e.g., service agreement, employment contract, NDA)\n" +
10
+ "2. Parties involved (company names, representative names, roles)\n" +
11
+ "3. Key terms (duration, amount, payment schedule)\n" +
12
+ "4. Number of signers and their names/roles\n" +
13
+ "5. Any special clauses or conditions\n\n" +
14
+ "Generate professional, legally-structured HTML with proper headings, articles, " +
15
+ "and signature blocks for each signer at the bottom. " +
16
+ "Do NOT include <html>/<head>/<body> wrapper — only the inner content.",
17
+ inputSchema: {
18
+ name: z.string(),
19
+ html: z.string(),
20
+ folderId: z.string().optional(),
21
+ },
22
+ }, async ({ name, html, folderId }) => {
23
+ try {
24
+ const result = await client.post("/contracts/create-from-html", { name, html, folderId });
25
+ const signingUrl = `${client.appUrl}/contracts/${result.id}/signing`;
26
+ return {
27
+ content: [{
28
+ type: "text",
29
+ text: JSON.stringify({
30
+ success: true,
31
+ contractId: result.id,
32
+ name: result.name,
33
+ fileSize: result.fileSize,
34
+ message: `Contract "${result.name}" created successfully.`,
35
+ signingWorkspaceUrl: signingUrl,
36
+ nextStep: "Open the signing workspace URL to place signature fields and send to signers.",
37
+ }, null, 2),
38
+ }],
39
+ };
40
+ }
41
+ catch (error) {
42
+ return {
43
+ content: [{ type: "text", text: `Error: ${error.message}` }],
44
+ isError: true,
45
+ };
46
+ }
47
+ });
48
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { AiDocxClient } from "../api-client.js";
3
+ export declare function register(server: McpServer, client: AiDocxClient): void;
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+ const inputSchema = {
3
+ name: z.string().describe("Folder name"),
4
+ parentId: z.string().optional().describe("Parent folder ID. Omit for root level."),
5
+ };
6
+ export function register(server, client) {
7
+ server.registerTool("create_folder", {
8
+ description: "Create a new folder in AiDocX document management.",
9
+ inputSchema,
10
+ }, async ({ name, parentId }) => {
11
+ try {
12
+ const result = await client.post("/contracts/folders", { name, parentId });
13
+ return {
14
+ content: [{
15
+ type: "text",
16
+ text: JSON.stringify({
17
+ success: true,
18
+ folderId: result.id,
19
+ name: result.name,
20
+ message: `Folder "${result.name}" created.`,
21
+ }, null, 2),
22
+ }],
23
+ };
24
+ }
25
+ catch (error) {
26
+ return {
27
+ content: [{ type: "text", text: `Error: ${error.message}` }],
28
+ isError: true,
29
+ };
30
+ }
31
+ });
32
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { AiDocxClient } from "../api-client.js";
3
+ export declare function register(server: McpServer, client: AiDocxClient): void;
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ const inputSchema = {
3
+ id: z.string().describe("Contract ID"),
4
+ };
5
+ export function register(server, client) {
6
+ server.registerTool("get_contract", {
7
+ description: "Get details of a specific contract in AiDocX. Returns name, type, size, and text extract.",
8
+ inputSchema,
9
+ }, async ({ id }) => {
10
+ try {
11
+ const result = await client.get(`/contracts/${id}`);
12
+ const contract = result.contract || result;
13
+ return {
14
+ content: [{
15
+ type: "text",
16
+ text: JSON.stringify({
17
+ id: contract.id, name: contract.name,
18
+ fileName: contract.fileName, fileType: contract.fileType,
19
+ fileSize: contract.fileSize, contentType: contract.contentType,
20
+ folderId: contract.folderId, labels: contract.labels,
21
+ textExtract: contract.textExtract,
22
+ createdAt: contract.createdAt, updatedAt: contract.updatedAt,
23
+ }, null, 2),
24
+ }],
25
+ };
26
+ }
27
+ catch (error) {
28
+ return {
29
+ content: [{ type: "text", text: `Error: ${error.message}` }],
30
+ isError: true,
31
+ };
32
+ }
33
+ });
34
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { AiDocxClient } from "../api-client.js";
3
+ export declare function register(server: McpServer, client: AiDocxClient): void;
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ const inputSchema = {
3
+ folderId: z.string().optional().describe("Folder ID to list. Omit for root folder."),
4
+ };
5
+ export function register(server, client) {
6
+ server.registerTool("list_contracts", {
7
+ description: "List contracts in the user's AiDocX document management.",
8
+ inputSchema,
9
+ }, async ({ folderId }) => {
10
+ try {
11
+ const params = {};
12
+ if (folderId)
13
+ params.folderId = folderId;
14
+ const result = await client.get("/contracts", params);
15
+ const contracts = result.contracts || result;
16
+ const summary = Array.isArray(contracts)
17
+ ? contracts.map((c) => ({
18
+ id: c.id, name: c.name, fileType: c.fileType,
19
+ fileSize: c.fileSize, contentType: c.contentType,
20
+ createdAt: c.createdAt, updatedAt: c.updatedAt,
21
+ }))
22
+ : contracts;
23
+ return {
24
+ content: [{
25
+ type: "text",
26
+ text: JSON.stringify({
27
+ count: Array.isArray(summary) ? summary.length : 0,
28
+ contracts: summary,
29
+ }, null, 2),
30
+ }],
31
+ };
32
+ }
33
+ catch (error) {
34
+ return {
35
+ content: [{ type: "text", text: `Error: ${error.message}` }],
36
+ isError: true,
37
+ };
38
+ }
39
+ });
40
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { AiDocxClient } from "../api-client.js";
3
+ export declare function register(server: McpServer, client: AiDocxClient): void;
@@ -0,0 +1,38 @@
1
+ import { z } from "zod";
2
+ const inputSchema = {
3
+ parentId: z.string().optional().describe("Parent folder ID. Omit for root-level folders."),
4
+ };
5
+ export function register(server, client) {
6
+ server.registerTool("list_folders", {
7
+ description: "List folders in the user's AiDocX document management.",
8
+ inputSchema,
9
+ }, async ({ parentId }) => {
10
+ try {
11
+ const params = {};
12
+ if (parentId)
13
+ params.parentId = parentId;
14
+ const result = await client.get("/contracts/folders", params);
15
+ const folders = result.folders || result;
16
+ const summary = Array.isArray(folders)
17
+ ? folders.map((f) => ({
18
+ id: f.id, name: f.name, parentId: f.parentId, createdAt: f.createdAt,
19
+ }))
20
+ : folders;
21
+ return {
22
+ content: [{
23
+ type: "text",
24
+ text: JSON.stringify({
25
+ count: Array.isArray(summary) ? summary.length : 0,
26
+ folders: summary,
27
+ }, null, 2),
28
+ }],
29
+ };
30
+ }
31
+ catch (error) {
32
+ return {
33
+ content: [{ type: "text", text: `Error: ${error.message}` }],
34
+ isError: true,
35
+ };
36
+ }
37
+ });
38
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { AiDocxClient } from "../api-client.js";
3
+ export declare function register(server: McpServer, client: AiDocxClient): void;
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ const inputSchema = {
3
+ fileName: z.string().describe("File name with extension (e.g., 'contract.pdf')"),
4
+ fileBase64: z.string().describe("Base64-encoded file content (max 50MB)"),
5
+ fileType: z.string().describe("MIME type (e.g., 'application/pdf')"),
6
+ folderId: z.string().optional().describe("Target folder ID. Omit for root."),
7
+ };
8
+ export function register(server, client) {
9
+ server.registerTool("upload_contract", {
10
+ description: "Upload a PDF or Office document (DOC, DOCX, HWP, XLS, XLSX, PPT, PPTX) to AiDocX. " +
11
+ "Office files are auto-converted to PDF.",
12
+ inputSchema,
13
+ }, async ({ fileName, fileBase64, fileType, folderId }) => {
14
+ try {
15
+ const result = await client.post("/contracts/upload", {
16
+ file: fileBase64, fileName, fileType, folderId,
17
+ });
18
+ const signingUrl = `${client.appUrl}/contracts/${result.id}/signing`;
19
+ return {
20
+ content: [{
21
+ type: "text",
22
+ text: JSON.stringify({
23
+ success: true,
24
+ contractId: result.id,
25
+ name: result.name,
26
+ fileSize: result.fileSize,
27
+ message: `File "${result.name}" uploaded successfully.`,
28
+ signingWorkspaceUrl: signingUrl,
29
+ nextStep: "Open the signing workspace URL to place signature fields and send to signers.",
30
+ }, null, 2),
31
+ }],
32
+ };
33
+ }
34
+ catch (error) {
35
+ return {
36
+ content: [{ type: "text", text: `Error: ${error.message}` }],
37
+ isError: true,
38
+ };
39
+ }
40
+ });
41
+ }
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "aidocx-mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "AiDocX MCP Server - Upload and manage contracts from Claude Desktop and other MCP clients",
5
+ "type": "module",
6
+ "bin": {
7
+ "aidocx-mcp": "./build/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node build/index.js",
12
+ "dev": "tsx src/index.ts"
13
+ },
14
+ "files": [
15
+ "build"
16
+ ],
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.12.0",
19
+ "zod": "^3.25.0"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^20.0.0",
23
+ "typescript": "^5.5.0",
24
+ "tsx": "^4.19.0"
25
+ }
26
+ }