argulens-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.
- package/README.md +77 -0
- package/dist/client.d.ts +10 -0
- package/dist/client.js +39 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +168 -0
- package/package.json +34 -0
- package/src/client.ts +58 -0
- package/src/index.ts +183 -0
- package/tsconfig.json +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# @argulens/mcp-server
|
|
2
|
+
|
|
3
|
+
MCP server for [ArguLens](https://argulens.com) — analyze legal documents directly from Claude, ChatGPT, or any MCP-compatible AI assistant.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### 1. Get an API key
|
|
8
|
+
|
|
9
|
+
1. Sign up at [argulens.com](https://argulens.com)
|
|
10
|
+
2. Go to [My Cases > API Keys](https://argulens.com/my-cases/api-keys)
|
|
11
|
+
3. Create a new API key
|
|
12
|
+
|
|
13
|
+
### 2. Install
|
|
14
|
+
|
|
15
|
+
#### Claude Desktop
|
|
16
|
+
|
|
17
|
+
Add to your `claude_desktop_config.json`:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"argulens": {
|
|
23
|
+
"command": "npx",
|
|
24
|
+
"args": ["@argulens/mcp-server"],
|
|
25
|
+
"env": {
|
|
26
|
+
"ARGULENS_API_KEY": "al_live_your_key_here"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Claude Code
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
claude mcp add argulens -- npx @argulens/mcp-server
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then set the environment variable:
|
|
40
|
+
```bash
|
|
41
|
+
export ARGULENS_API_KEY=al_live_your_key_here
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Available Tools
|
|
45
|
+
|
|
46
|
+
| Tool | Description |
|
|
47
|
+
|------|-------------|
|
|
48
|
+
| `analyze_case` | Upload documents and get a 7-section case pack (summary, timeline, evidence, risks, etc.) |
|
|
49
|
+
| `chat_about_case` | Ask evidence-grounded follow-up questions about a case |
|
|
50
|
+
| `parse_document` | Extract text from PDF, DOCX, images (OCR), or email files |
|
|
51
|
+
| `draft_document` | Generate court-ready documents (affidavits, submissions, defence notices) |
|
|
52
|
+
| `check_usage` | Check your current usage and remaining quota |
|
|
53
|
+
|
|
54
|
+
## Usage Examples
|
|
55
|
+
|
|
56
|
+
Once configured, you can ask your AI assistant:
|
|
57
|
+
|
|
58
|
+
- "Analyze this divorce petition and tell me my strengths and weaknesses"
|
|
59
|
+
- "What are the risks in my custody case based on these documents?"
|
|
60
|
+
- "Draft an affidavit based on my case analysis"
|
|
61
|
+
- "How much of my ArguLens quota have I used this month?"
|
|
62
|
+
|
|
63
|
+
## Billing
|
|
64
|
+
|
|
65
|
+
Usage through MCP counts against your ArguLens plan:
|
|
66
|
+
|
|
67
|
+
- **Free**: 50 analyses/month, 100 chat messages/month
|
|
68
|
+
- **Pro** ($11/month): 100 analyses/month, 200 chat messages/month
|
|
69
|
+
|
|
70
|
+
When you hit your limit, the tool will return an error with a link to upgrade.
|
|
71
|
+
|
|
72
|
+
## Environment Variables
|
|
73
|
+
|
|
74
|
+
| Variable | Required | Description |
|
|
75
|
+
|----------|----------|-------------|
|
|
76
|
+
| `ARGULENS_API_KEY` | Yes | Your ArguLens API key (starts with `al_live_`) |
|
|
77
|
+
| `ARGULENS_BASE_URL` | No | Custom API URL (defaults to `https://argulens.com`) |
|
package/dist/client.d.ts
ADDED
package/dist/client.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const BASE_URL = process.env.ARGULENS_BASE_URL || "https://argulens.com";
|
|
2
|
+
const API_KEY = process.env.ARGULENS_API_KEY;
|
|
3
|
+
if (!API_KEY) {
|
|
4
|
+
console.error("ARGULENS_API_KEY environment variable is required");
|
|
5
|
+
process.exit(1);
|
|
6
|
+
}
|
|
7
|
+
export class ArguLensClient {
|
|
8
|
+
baseUrl;
|
|
9
|
+
apiKey;
|
|
10
|
+
constructor() {
|
|
11
|
+
this.baseUrl = BASE_URL;
|
|
12
|
+
this.apiKey = API_KEY;
|
|
13
|
+
}
|
|
14
|
+
async request(path, options = {}) {
|
|
15
|
+
const { method = "GET", body } = options;
|
|
16
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
17
|
+
method,
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
"User-Agent": "argulens-mcp/0.1.0",
|
|
22
|
+
},
|
|
23
|
+
...(body ? { body: JSON.stringify(body) } : {}),
|
|
24
|
+
});
|
|
25
|
+
if (!res.ok) {
|
|
26
|
+
const error = await res.json().catch(() => ({ error: res.statusText }));
|
|
27
|
+
const message = error.error || res.statusText;
|
|
28
|
+
if (res.status === 401) {
|
|
29
|
+
throw new Error(`Invalid or revoked API key. Generate a new key at ${this.baseUrl}/my-cases/api-keys`);
|
|
30
|
+
}
|
|
31
|
+
if (res.status === 429) {
|
|
32
|
+
throw new Error(`Rate limit or quota exceeded. Upgrade your plan at ${this.baseUrl}/pricing`);
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`ArguLens API error (${res.status}): ${message}`);
|
|
35
|
+
}
|
|
36
|
+
return res.json();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export const client = new ArguLensClient();
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
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 { z } from "zod";
|
|
5
|
+
import { client } from "./client.js";
|
|
6
|
+
const server = new McpServer({
|
|
7
|
+
name: "argulens",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
});
|
|
10
|
+
// Tool: analyze_case
|
|
11
|
+
server.registerTool("analyze_case", {
|
|
12
|
+
title: "Analyze Legal Case",
|
|
13
|
+
description: "Upload legal documents and get a structured 7-section case pack: summary, timeline, evidence index, missing evidence, risks, opposing arguments, and response draft. Supports Singapore family law (Women's Charter, HDB, CPF) and worldwide disputes.",
|
|
14
|
+
inputSchema: {
|
|
15
|
+
documentTexts: z
|
|
16
|
+
.array(z.object({
|
|
17
|
+
name: z.string().describe("Document filename"),
|
|
18
|
+
content: z.string().describe("Extracted text content of the document"),
|
|
19
|
+
}))
|
|
20
|
+
.describe("Array of documents with name and text content"),
|
|
21
|
+
caseType: z
|
|
22
|
+
.enum([
|
|
23
|
+
"divorce",
|
|
24
|
+
"annulment",
|
|
25
|
+
"custody",
|
|
26
|
+
"support",
|
|
27
|
+
"property",
|
|
28
|
+
"landlord-tenant",
|
|
29
|
+
"contract",
|
|
30
|
+
"personal-injury",
|
|
31
|
+
"employment",
|
|
32
|
+
"immigration",
|
|
33
|
+
"other",
|
|
34
|
+
])
|
|
35
|
+
.describe("Type of legal case"),
|
|
36
|
+
role: z
|
|
37
|
+
.enum(["plaintiff", "defendant", "petitioner", "respondent", "applicant"])
|
|
38
|
+
.describe("Your role in the case"),
|
|
39
|
+
jurisdiction: z
|
|
40
|
+
.string()
|
|
41
|
+
.default("Singapore")
|
|
42
|
+
.describe("Jurisdiction (e.g. Singapore, Malaysia, India)"),
|
|
43
|
+
},
|
|
44
|
+
}, async ({ documentTexts, caseType, role, jurisdiction }) => {
|
|
45
|
+
const result = await client.request("/api/analyze", {
|
|
46
|
+
method: "POST",
|
|
47
|
+
body: { documentTexts, caseType, role, jurisdiction },
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
content: [
|
|
51
|
+
{
|
|
52
|
+
type: "text",
|
|
53
|
+
text: JSON.stringify(result, null, 2),
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
// Tool: chat_about_case
|
|
59
|
+
server.registerTool("chat_about_case", {
|
|
60
|
+
title: "Chat About a Legal Case",
|
|
61
|
+
description: "Ask evidence-grounded questions about a legal case. Every answer cites specific uploaded documents. Useful for follow-up questions after analyzing a case.",
|
|
62
|
+
inputSchema: {
|
|
63
|
+
message: z.string().describe("Your question about the case"),
|
|
64
|
+
caseId: z
|
|
65
|
+
.string()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("Case ID from a previous analysis (optional)"),
|
|
68
|
+
},
|
|
69
|
+
}, async ({ message, caseId }) => {
|
|
70
|
+
const result = await client.request("/api/chat", {
|
|
71
|
+
method: "POST",
|
|
72
|
+
body: {
|
|
73
|
+
messages: [{ role: "user", content: message }],
|
|
74
|
+
...(caseId ? { caseId } : {}),
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: "text",
|
|
81
|
+
text: JSON.stringify(result, null, 2),
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
// Tool: parse_document
|
|
87
|
+
server.registerTool("parse_document", {
|
|
88
|
+
title: "Parse Legal Document",
|
|
89
|
+
description: "Extract text from a legal document file. Supports PDF, DOCX, images (OCR), and email files. Returns the extracted text content.",
|
|
90
|
+
inputSchema: {
|
|
91
|
+
fileBase64: z
|
|
92
|
+
.string()
|
|
93
|
+
.describe("Base64-encoded file content"),
|
|
94
|
+
filename: z
|
|
95
|
+
.string()
|
|
96
|
+
.describe("Filename with extension (e.g. notice.pdf, contract.docx)"),
|
|
97
|
+
},
|
|
98
|
+
}, async ({ fileBase64, filename }) => {
|
|
99
|
+
const result = await client.request("/api/parse", {
|
|
100
|
+
method: "POST",
|
|
101
|
+
body: { file: fileBase64, filename },
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
content: [
|
|
105
|
+
{
|
|
106
|
+
type: "text",
|
|
107
|
+
text: JSON.stringify(result, null, 2),
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
// Tool: draft_document
|
|
113
|
+
server.registerTool("draft_document", {
|
|
114
|
+
title: "Draft Legal Document",
|
|
115
|
+
description: "Generate a court-ready legal document from case analysis. Supported types: notice of contest, reply to defence, affidavit, written submissions, request for discovery.",
|
|
116
|
+
inputSchema: {
|
|
117
|
+
caseId: z.string().describe("Case ID from a previous analysis"),
|
|
118
|
+
documentType: z
|
|
119
|
+
.enum([
|
|
120
|
+
"notice-of-contest",
|
|
121
|
+
"reply-to-defence",
|
|
122
|
+
"affidavit-general",
|
|
123
|
+
"affidavit-assets-means",
|
|
124
|
+
"written-submissions",
|
|
125
|
+
"request-for-discovery",
|
|
126
|
+
"notice-act-in-person",
|
|
127
|
+
])
|
|
128
|
+
.describe("Type of legal document to generate"),
|
|
129
|
+
instructions: z
|
|
130
|
+
.string()
|
|
131
|
+
.optional()
|
|
132
|
+
.describe("Additional instructions for the document"),
|
|
133
|
+
},
|
|
134
|
+
}, async ({ caseId, documentType, instructions }) => {
|
|
135
|
+
const result = await client.request("/api/draft", {
|
|
136
|
+
method: "POST",
|
|
137
|
+
body: { caseId, documentType, instructions },
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
content: [
|
|
141
|
+
{
|
|
142
|
+
type: "text",
|
|
143
|
+
text: JSON.stringify(result, null, 2),
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
// Tool: check_usage
|
|
149
|
+
server.registerTool("check_usage", {
|
|
150
|
+
title: "Check Usage & Quota",
|
|
151
|
+
description: "Check your current ArguLens usage and remaining quota for analyses and chat messages.",
|
|
152
|
+
}, async () => {
|
|
153
|
+
const result = await client.request("/api/usage");
|
|
154
|
+
return {
|
|
155
|
+
content: [
|
|
156
|
+
{
|
|
157
|
+
type: "text",
|
|
158
|
+
text: JSON.stringify(result, null, 2),
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
// Start the server
|
|
164
|
+
const transport = new StdioServerTransport();
|
|
165
|
+
server.connect(transport).catch((err) => {
|
|
166
|
+
console.error("Failed to start ArguLens MCP server:", err.message);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "argulens-mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for ArguLens — analyze legal documents from any AI assistant",
|
|
5
|
+
"bin": {
|
|
6
|
+
"argulens-mcp-server": "dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@modelcontextprotocol/sdk": "^1.12.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.7.0",
|
|
19
|
+
"@types/node": "^22.0.0"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"mcp",
|
|
23
|
+
"legal",
|
|
24
|
+
"singapore",
|
|
25
|
+
"family-law",
|
|
26
|
+
"document-analysis",
|
|
27
|
+
"argulens"
|
|
28
|
+
],
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/venkata-srinivasan/argulens"
|
|
33
|
+
}
|
|
34
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const BASE_URL = process.env.ARGULENS_BASE_URL || "https://argulens.com"
|
|
2
|
+
const API_KEY = process.env.ARGULENS_API_KEY
|
|
3
|
+
|
|
4
|
+
if (!API_KEY) {
|
|
5
|
+
console.error("ARGULENS_API_KEY environment variable is required")
|
|
6
|
+
process.exit(1)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class ArguLensClient {
|
|
10
|
+
private baseUrl: string
|
|
11
|
+
private apiKey: string
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
14
|
+
this.baseUrl = BASE_URL
|
|
15
|
+
this.apiKey = API_KEY!
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async request(
|
|
19
|
+
path: string,
|
|
20
|
+
options: {
|
|
21
|
+
method?: string
|
|
22
|
+
body?: unknown
|
|
23
|
+
} = {}
|
|
24
|
+
): Promise<unknown> {
|
|
25
|
+
const { method = "GET", body } = options
|
|
26
|
+
|
|
27
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
28
|
+
method,
|
|
29
|
+
headers: {
|
|
30
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
"User-Agent": "argulens-mcp/0.1.0",
|
|
33
|
+
},
|
|
34
|
+
...(body ? { body: JSON.stringify(body) } : {}),
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
if (!res.ok) {
|
|
38
|
+
const error = await res.json().catch(() => ({ error: res.statusText }))
|
|
39
|
+
const message = (error as { error?: string }).error || res.statusText
|
|
40
|
+
|
|
41
|
+
if (res.status === 401) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Invalid or revoked API key. Generate a new key at ${this.baseUrl}/my-cases/api-keys`
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
if (res.status === 429) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Rate limit or quota exceeded. Upgrade your plan at ${this.baseUrl}/pricing`
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`ArguLens API error (${res.status}): ${message}`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return res.json()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const client = new ArguLensClient()
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
5
|
+
import { z } from "zod"
|
|
6
|
+
import { client } from "./client.js"
|
|
7
|
+
|
|
8
|
+
const server = new McpServer({
|
|
9
|
+
name: "argulens",
|
|
10
|
+
version: "0.1.0",
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
// Tool: analyze_case
|
|
14
|
+
server.registerTool("analyze_case", {
|
|
15
|
+
title: "Analyze Legal Case",
|
|
16
|
+
description:
|
|
17
|
+
"Upload legal documents and get a structured 7-section case pack: summary, timeline, evidence index, missing evidence, risks, opposing arguments, and response draft. Supports Singapore family law (Women's Charter, HDB, CPF) and worldwide disputes.",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
documentTexts: z
|
|
20
|
+
.array(
|
|
21
|
+
z.object({
|
|
22
|
+
name: z.string().describe("Document filename"),
|
|
23
|
+
content: z.string().describe("Extracted text content of the document"),
|
|
24
|
+
})
|
|
25
|
+
)
|
|
26
|
+
.describe("Array of documents with name and text content"),
|
|
27
|
+
caseType: z
|
|
28
|
+
.enum([
|
|
29
|
+
"divorce",
|
|
30
|
+
"annulment",
|
|
31
|
+
"custody",
|
|
32
|
+
"support",
|
|
33
|
+
"property",
|
|
34
|
+
"landlord-tenant",
|
|
35
|
+
"contract",
|
|
36
|
+
"personal-injury",
|
|
37
|
+
"employment",
|
|
38
|
+
"immigration",
|
|
39
|
+
"other",
|
|
40
|
+
])
|
|
41
|
+
.describe("Type of legal case"),
|
|
42
|
+
role: z
|
|
43
|
+
.enum(["plaintiff", "defendant", "petitioner", "respondent", "applicant"])
|
|
44
|
+
.describe("Your role in the case"),
|
|
45
|
+
jurisdiction: z
|
|
46
|
+
.string()
|
|
47
|
+
.default("Singapore")
|
|
48
|
+
.describe("Jurisdiction (e.g. Singapore, Malaysia, India)"),
|
|
49
|
+
},
|
|
50
|
+
}, async ({ documentTexts, caseType, role, jurisdiction }) => {
|
|
51
|
+
const result = await client.request("/api/analyze", {
|
|
52
|
+
method: "POST",
|
|
53
|
+
body: { documentTexts, caseType, role, jurisdiction },
|
|
54
|
+
})
|
|
55
|
+
return {
|
|
56
|
+
content: [
|
|
57
|
+
{
|
|
58
|
+
type: "text" as const,
|
|
59
|
+
text: JSON.stringify(result, null, 2),
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// Tool: chat_about_case
|
|
66
|
+
server.registerTool("chat_about_case", {
|
|
67
|
+
title: "Chat About a Legal Case",
|
|
68
|
+
description:
|
|
69
|
+
"Ask evidence-grounded questions about a legal case. Every answer cites specific uploaded documents. Useful for follow-up questions after analyzing a case.",
|
|
70
|
+
inputSchema: {
|
|
71
|
+
message: z.string().describe("Your question about the case"),
|
|
72
|
+
caseId: z
|
|
73
|
+
.string()
|
|
74
|
+
.optional()
|
|
75
|
+
.describe("Case ID from a previous analysis (optional)"),
|
|
76
|
+
},
|
|
77
|
+
}, async ({ message, caseId }) => {
|
|
78
|
+
const result = await client.request("/api/chat", {
|
|
79
|
+
method: "POST",
|
|
80
|
+
body: {
|
|
81
|
+
messages: [{ role: "user", content: message }],
|
|
82
|
+
...(caseId ? { caseId } : {}),
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
return {
|
|
86
|
+
content: [
|
|
87
|
+
{
|
|
88
|
+
type: "text" as const,
|
|
89
|
+
text: JSON.stringify(result, null, 2),
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// Tool: parse_document
|
|
96
|
+
server.registerTool("parse_document", {
|
|
97
|
+
title: "Parse Legal Document",
|
|
98
|
+
description:
|
|
99
|
+
"Extract text from a legal document file. Supports PDF, DOCX, images (OCR), and email files. Returns the extracted text content.",
|
|
100
|
+
inputSchema: {
|
|
101
|
+
fileBase64: z
|
|
102
|
+
.string()
|
|
103
|
+
.describe("Base64-encoded file content"),
|
|
104
|
+
filename: z
|
|
105
|
+
.string()
|
|
106
|
+
.describe("Filename with extension (e.g. notice.pdf, contract.docx)"),
|
|
107
|
+
},
|
|
108
|
+
}, async ({ fileBase64, filename }) => {
|
|
109
|
+
const result = await client.request("/api/parse", {
|
|
110
|
+
method: "POST",
|
|
111
|
+
body: { file: fileBase64, filename },
|
|
112
|
+
})
|
|
113
|
+
return {
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: "text" as const,
|
|
117
|
+
text: JSON.stringify(result, null, 2),
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
// Tool: draft_document
|
|
124
|
+
server.registerTool("draft_document", {
|
|
125
|
+
title: "Draft Legal Document",
|
|
126
|
+
description:
|
|
127
|
+
"Generate a court-ready legal document from case analysis. Supported types: notice of contest, reply to defence, affidavit, written submissions, request for discovery.",
|
|
128
|
+
inputSchema: {
|
|
129
|
+
caseId: z.string().describe("Case ID from a previous analysis"),
|
|
130
|
+
documentType: z
|
|
131
|
+
.enum([
|
|
132
|
+
"notice-of-contest",
|
|
133
|
+
"reply-to-defence",
|
|
134
|
+
"affidavit-general",
|
|
135
|
+
"affidavit-assets-means",
|
|
136
|
+
"written-submissions",
|
|
137
|
+
"request-for-discovery",
|
|
138
|
+
"notice-act-in-person",
|
|
139
|
+
])
|
|
140
|
+
.describe("Type of legal document to generate"),
|
|
141
|
+
instructions: z
|
|
142
|
+
.string()
|
|
143
|
+
.optional()
|
|
144
|
+
.describe("Additional instructions for the document"),
|
|
145
|
+
},
|
|
146
|
+
}, async ({ caseId, documentType, instructions }) => {
|
|
147
|
+
const result = await client.request("/api/draft", {
|
|
148
|
+
method: "POST",
|
|
149
|
+
body: { caseId, documentType, instructions },
|
|
150
|
+
})
|
|
151
|
+
return {
|
|
152
|
+
content: [
|
|
153
|
+
{
|
|
154
|
+
type: "text" as const,
|
|
155
|
+
text: JSON.stringify(result, null, 2),
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// Tool: check_usage
|
|
162
|
+
server.registerTool("check_usage", {
|
|
163
|
+
title: "Check Usage & Quota",
|
|
164
|
+
description:
|
|
165
|
+
"Check your current ArguLens usage and remaining quota for analyses and chat messages.",
|
|
166
|
+
}, async () => {
|
|
167
|
+
const result = await client.request("/api/usage")
|
|
168
|
+
return {
|
|
169
|
+
content: [
|
|
170
|
+
{
|
|
171
|
+
type: "text" as const,
|
|
172
|
+
text: JSON.stringify(result, null, 2),
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
// Start the server
|
|
179
|
+
const transport = new StdioServerTransport()
|
|
180
|
+
server.connect(transport).catch((err: Error) => {
|
|
181
|
+
console.error("Failed to start ArguLens MCP server:", err.message)
|
|
182
|
+
process.exit(1)
|
|
183
|
+
})
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "Node16",
|
|
5
|
+
"moduleResolution": "Node16",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"declaration": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src"]
|
|
14
|
+
}
|