aig-risk-profiler-mcp 1.0.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 +192 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +89 -0
- package/dist/index.js.map +1 -0
- package/dist/services/api-client.d.ts +31 -0
- package/dist/services/api-client.d.ts.map +1 -0
- package/dist/services/api-client.js +93 -0
- package/dist/services/api-client.js.map +1 -0
- package/dist/services/pdf-generator.d.ts +22 -0
- package/dist/services/pdf-generator.d.ts.map +1 -0
- package/dist/services/pdf-generator.js +236 -0
- package/dist/services/pdf-generator.js.map +1 -0
- package/dist/tools/analyze.d.ts +28 -0
- package/dist/tools/analyze.d.ts.map +1 -0
- package/dist/tools/analyze.js +30 -0
- package/dist/tools/analyze.js.map +1 -0
- package/dist/tools/get-report.d.ts +42 -0
- package/dist/tools/get-report.d.ts.map +1 -0
- package/dist/tools/get-report.js +70 -0
- package/dist/tools/get-report.js.map +1 -0
- package/dist/types/index.d.ts +41 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# aig-risk-profiler-mcp
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server for generating Management Liability Coverage (MLC) risk analysis reports from Chinese company annual report PDFs.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **analyze_company**: Upload a company annual report PDF and start analysis
|
|
8
|
+
- **get_report**: Retrieve the completed analysis as a professionally formatted PDF
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- Node.js >= 18.0.0
|
|
13
|
+
- The MLC Agent backend must be running (see backend setup instructions)
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### From npm
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g aig-risk-profiler-mcp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### From source
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git clone <repository-url>
|
|
27
|
+
cd mcp-server
|
|
28
|
+
pnpm install
|
|
29
|
+
pnpm build
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage with Claude Desktop
|
|
33
|
+
|
|
34
|
+
Add the following to your Claude Desktop configuration file:
|
|
35
|
+
|
|
36
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
37
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
38
|
+
|
|
39
|
+
### Using npx (recommended)
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"aig-risk-profiler": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["-y", "aig-risk-profiler-mcp"],
|
|
47
|
+
"env": {
|
|
48
|
+
"BACKEND_URL": "http://localhost:8000"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Using global install
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"aig-risk-profiler": {
|
|
61
|
+
"command": "aig-risk-profiler-mcp",
|
|
62
|
+
"env": {
|
|
63
|
+
"BACKEND_URL": "http://localhost:8000"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Using local build
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"aig-risk-profiler": {
|
|
76
|
+
"command": "node",
|
|
77
|
+
"args": ["/path/to/mcp-server/dist/index.js"],
|
|
78
|
+
"env": {
|
|
79
|
+
"BACKEND_URL": "http://localhost:8000"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Environment Variables
|
|
87
|
+
|
|
88
|
+
| Variable | Description | Default |
|
|
89
|
+
|----------|-------------|---------|
|
|
90
|
+
| `BACKEND_URL` | URL of the MLC Agent backend API | `http://localhost:8000` |
|
|
91
|
+
| `OUTPUT_DIR` | Directory to save generated PDF reports | `~/mlc-reports/` |
|
|
92
|
+
|
|
93
|
+
## Tools
|
|
94
|
+
|
|
95
|
+
### analyze_company
|
|
96
|
+
|
|
97
|
+
Upload a Chinese company annual report PDF and start MLC analysis.
|
|
98
|
+
|
|
99
|
+
**Input:**
|
|
100
|
+
- `pdf_path` (required): Local file path to the company annual report PDF
|
|
101
|
+
|
|
102
|
+
**Output:**
|
|
103
|
+
- `task_id`: ID to track the analysis task
|
|
104
|
+
- `status`: Current status of the task
|
|
105
|
+
- `message`: Human-readable message
|
|
106
|
+
|
|
107
|
+
**Example:**
|
|
108
|
+
```
|
|
109
|
+
User: Analyze the annual report at /Users/me/Documents/company_2023.pdf
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### get_report
|
|
113
|
+
|
|
114
|
+
Retrieve the MLC analysis report for a completed task and convert it to PDF.
|
|
115
|
+
|
|
116
|
+
**Input:**
|
|
117
|
+
- `task_id` (required): The task ID returned by analyze_company
|
|
118
|
+
- `wait_for_completion` (optional): Whether to wait for task completion (default: true)
|
|
119
|
+
- `output_filename` (optional): Custom filename for the PDF
|
|
120
|
+
|
|
121
|
+
**Output:**
|
|
122
|
+
- `pdf_path`: Path to the generated PDF file
|
|
123
|
+
- `company_name`: Name of the analyzed company
|
|
124
|
+
- `is_listed`: Whether the company is publicly listed
|
|
125
|
+
- `is_soe`: Whether the company is a state-owned enterprise
|
|
126
|
+
- `message`: Human-readable message
|
|
127
|
+
|
|
128
|
+
**Example:**
|
|
129
|
+
```
|
|
130
|
+
User: Get the report for task 42
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Development
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Install dependencies
|
|
137
|
+
pnpm install
|
|
138
|
+
|
|
139
|
+
# Run in development mode
|
|
140
|
+
pnpm dev
|
|
141
|
+
|
|
142
|
+
# Type check
|
|
143
|
+
pnpm typecheck
|
|
144
|
+
|
|
145
|
+
# Build for production
|
|
146
|
+
pnpm build
|
|
147
|
+
|
|
148
|
+
# Run production build
|
|
149
|
+
pnpm start
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## PDF Output
|
|
153
|
+
|
|
154
|
+
Generated PDF reports are saved to `~/mlc-reports/` by default. Each report includes:
|
|
155
|
+
|
|
156
|
+
- Company overview
|
|
157
|
+
- Financial analysis
|
|
158
|
+
- Governance structure
|
|
159
|
+
- Shareholder information
|
|
160
|
+
- News and regulatory findings
|
|
161
|
+
- Risk assessment
|
|
162
|
+
- Works cited / data sources
|
|
163
|
+
|
|
164
|
+
The PDF is professionally styled with:
|
|
165
|
+
- Clear typography and hierarchy
|
|
166
|
+
- Table formatting
|
|
167
|
+
- Risk indicators
|
|
168
|
+
- Print-optimized layout
|
|
169
|
+
|
|
170
|
+
## Troubleshooting
|
|
171
|
+
|
|
172
|
+
### Backend connection refused
|
|
173
|
+
|
|
174
|
+
Make sure the MLC Agent backend is running:
|
|
175
|
+
```bash
|
|
176
|
+
cd backend
|
|
177
|
+
docker compose up -d
|
|
178
|
+
# or
|
|
179
|
+
uv run uvicorn mlc_agent.main:app --port 8000
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Task timeout
|
|
183
|
+
|
|
184
|
+
Analysis can take several minutes for large PDFs. The default timeout is 10 minutes. If you have a very large document, check the backend logs for progress.
|
|
185
|
+
|
|
186
|
+
### PDF generation fails
|
|
187
|
+
|
|
188
|
+
Ensure you have write permissions to the output directory. You can set a custom output directory via the `OUTPUT_DIR` environment variable.
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { ApiClient } from "./services/api-client.js";
|
|
6
|
+
import { PdfGenerator } from "./services/pdf-generator.js";
|
|
7
|
+
import { analyzeCompany, analyzeCompanySchema, } from "./tools/analyze.js";
|
|
8
|
+
import { getReport, getReportSchema, } from "./tools/get-report.js";
|
|
9
|
+
// Get configuration from environment
|
|
10
|
+
const BACKEND_URL = process.env.BACKEND_URL || "http://localhost:8000";
|
|
11
|
+
const OUTPUT_DIR = process.env.OUTPUT_DIR; // Optional, defaults to ~/mlc-reports/
|
|
12
|
+
// Initialize services
|
|
13
|
+
const apiClient = new ApiClient(BACKEND_URL);
|
|
14
|
+
const pdfGenerator = new PdfGenerator(OUTPUT_DIR);
|
|
15
|
+
// Create MCP server
|
|
16
|
+
const server = new Server({
|
|
17
|
+
name: "aig-risk-profiler-mcp",
|
|
18
|
+
version: "1.0.0",
|
|
19
|
+
}, {
|
|
20
|
+
capabilities: {
|
|
21
|
+
tools: {},
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
// Register tool listing handler
|
|
25
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
26
|
+
return {
|
|
27
|
+
tools: [analyzeCompanySchema, getReportSchema],
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
// Register tool execution handler
|
|
31
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
32
|
+
const { name, arguments: args } = request.params;
|
|
33
|
+
try {
|
|
34
|
+
switch (name) {
|
|
35
|
+
case "analyze_company": {
|
|
36
|
+
const input = args;
|
|
37
|
+
const result = await analyzeCompany(apiClient, input);
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: "text",
|
|
42
|
+
text: JSON.stringify(result, null, 2),
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
case "get_report": {
|
|
48
|
+
const input = args;
|
|
49
|
+
const result = await getReport(apiClient, pdfGenerator, input);
|
|
50
|
+
return {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
text: JSON.stringify(result, null, 2),
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
default:
|
|
60
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
65
|
+
return {
|
|
66
|
+
content: [
|
|
67
|
+
{
|
|
68
|
+
type: "text",
|
|
69
|
+
text: JSON.stringify({ error: errorMessage }, null, 2),
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
isError: true,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
// Start the server
|
|
77
|
+
async function main() {
|
|
78
|
+
const transport = new StdioServerTransport();
|
|
79
|
+
await server.connect(transport);
|
|
80
|
+
// Log to stderr so it doesn't interfere with MCP protocol on stdout
|
|
81
|
+
console.error(`MLC Agent MCP Server started`);
|
|
82
|
+
console.error(`Backend URL: ${BACKEND_URL}`);
|
|
83
|
+
console.error(`PDF Output Directory: ${pdfGenerator.getOutputDir()}`);
|
|
84
|
+
}
|
|
85
|
+
main().catch((error) => {
|
|
86
|
+
console.error("Fatal error:", error);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Task, CreateTaskResponse, HealthResponse } from "../types/index.js";
|
|
2
|
+
export declare class ApiClient {
|
|
3
|
+
private client;
|
|
4
|
+
constructor(baseUrl?: string);
|
|
5
|
+
/**
|
|
6
|
+
* Upload a PDF file and create an analysis task
|
|
7
|
+
*/
|
|
8
|
+
uploadPdf(filePath: string): Promise<CreateTaskResponse>;
|
|
9
|
+
/**
|
|
10
|
+
* Get the status of a task
|
|
11
|
+
*/
|
|
12
|
+
getTaskStatus(taskId: number): Promise<Task>;
|
|
13
|
+
/**
|
|
14
|
+
* Get the markdown report for a completed task
|
|
15
|
+
*/
|
|
16
|
+
getReport(taskId: number): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Poll for task completion with configurable interval and timeout
|
|
19
|
+
*/
|
|
20
|
+
waitForCompletion(taskId: number, options?: {
|
|
21
|
+
pollInterval?: number;
|
|
22
|
+
timeout?: number;
|
|
23
|
+
onProgress?: (task: Task) => void;
|
|
24
|
+
}): Promise<Task>;
|
|
25
|
+
/**
|
|
26
|
+
* Check backend health
|
|
27
|
+
*/
|
|
28
|
+
checkHealth(): Promise<HealthResponse>;
|
|
29
|
+
private sleep;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/services/api-client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAElF,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgB;gBAElB,OAAO,GAAE,MAAgC;IAOrD;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAsC9D;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUhD;;OAEG;IACG,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;QACP,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;KAC9B,GACL,OAAO,CAAC,IAAI,CAAC;IA+BhB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC;IAK5C,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import FormData from "form-data";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
export class ApiClient {
|
|
6
|
+
client;
|
|
7
|
+
constructor(baseUrl = "http://localhost:8000") {
|
|
8
|
+
this.client = axios.create({
|
|
9
|
+
baseURL: baseUrl,
|
|
10
|
+
timeout: 60000, // 60 second timeout for uploads
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Upload a PDF file and create an analysis task
|
|
15
|
+
*/
|
|
16
|
+
async uploadPdf(filePath) {
|
|
17
|
+
const absolutePath = path.resolve(filePath);
|
|
18
|
+
if (!fs.existsSync(absolutePath)) {
|
|
19
|
+
throw new Error(`File not found: ${absolutePath}`);
|
|
20
|
+
}
|
|
21
|
+
const fileStats = fs.statSync(absolutePath);
|
|
22
|
+
if (!fileStats.isFile()) {
|
|
23
|
+
throw new Error(`Path is not a file: ${absolutePath}`);
|
|
24
|
+
}
|
|
25
|
+
const fileName = path.basename(absolutePath);
|
|
26
|
+
if (!fileName.toLowerCase().endsWith(".pdf")) {
|
|
27
|
+
throw new Error(`File must be a PDF: ${fileName}`);
|
|
28
|
+
}
|
|
29
|
+
const form = new FormData();
|
|
30
|
+
form.append("file", fs.createReadStream(absolutePath), {
|
|
31
|
+
filename: fileName,
|
|
32
|
+
contentType: "application/pdf",
|
|
33
|
+
});
|
|
34
|
+
const response = await this.client.post("/api/tasks", form, {
|
|
35
|
+
headers: {
|
|
36
|
+
...form.getHeaders(),
|
|
37
|
+
},
|
|
38
|
+
maxContentLength: Infinity,
|
|
39
|
+
maxBodyLength: Infinity,
|
|
40
|
+
});
|
|
41
|
+
return response.data;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the status of a task
|
|
45
|
+
*/
|
|
46
|
+
async getTaskStatus(taskId) {
|
|
47
|
+
const response = await this.client.get(`/api/tasks/${taskId}`);
|
|
48
|
+
return response.data;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get the markdown report for a completed task
|
|
52
|
+
*/
|
|
53
|
+
async getReport(taskId) {
|
|
54
|
+
const response = await this.client.get(`/api/tasks/${taskId}/report`, {
|
|
55
|
+
responseType: "text",
|
|
56
|
+
});
|
|
57
|
+
return response.data;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Poll for task completion with configurable interval and timeout
|
|
61
|
+
*/
|
|
62
|
+
async waitForCompletion(taskId, options = {}) {
|
|
63
|
+
const { pollInterval = 5000, timeout = 600000, onProgress } = options;
|
|
64
|
+
const startTime = Date.now();
|
|
65
|
+
while (true) {
|
|
66
|
+
const task = await this.getTaskStatus(taskId);
|
|
67
|
+
if (onProgress) {
|
|
68
|
+
onProgress(task);
|
|
69
|
+
}
|
|
70
|
+
if (task.status === "completed") {
|
|
71
|
+
return task;
|
|
72
|
+
}
|
|
73
|
+
if (task.status === "failed") {
|
|
74
|
+
throw new Error(`Task failed: ${task.error_message || "Unknown error"}`);
|
|
75
|
+
}
|
|
76
|
+
if (Date.now() - startTime > timeout) {
|
|
77
|
+
throw new Error(`Task timed out after ${timeout / 1000} seconds. Current status: ${task.status}`);
|
|
78
|
+
}
|
|
79
|
+
await this.sleep(pollInterval);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check backend health
|
|
84
|
+
*/
|
|
85
|
+
async checkHealth() {
|
|
86
|
+
const response = await this.client.get("/health");
|
|
87
|
+
return response.data;
|
|
88
|
+
}
|
|
89
|
+
sleep(ms) {
|
|
90
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/services/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface PdfGeneratorOptions {
|
|
2
|
+
outputDir?: string;
|
|
3
|
+
filename?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class PdfGenerator {
|
|
6
|
+
private outputDir;
|
|
7
|
+
constructor(outputDir?: string);
|
|
8
|
+
private ensureOutputDir;
|
|
9
|
+
/**
|
|
10
|
+
* Convert markdown content to PDF and save to file
|
|
11
|
+
*/
|
|
12
|
+
generatePdf(markdown: string, options?: PdfGeneratorOptions): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Get CSS stylesheet for professional report styling
|
|
15
|
+
*/
|
|
16
|
+
private getStylesheet;
|
|
17
|
+
/**
|
|
18
|
+
* Get the output directory path
|
|
19
|
+
*/
|
|
20
|
+
getOutputDir(): string;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=pdf-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf-generator.d.ts","sourceRoot":"","sources":["../../src/services/pdf-generator.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,CAAC,EAAE,MAAM;IAK9B,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACG,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC;IAwClB;;OAEG;IACH,OAAO,CAAC,aAAa;IAiLrB;;OAEG;IACH,YAAY,IAAI,MAAM;CAGvB"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { mdToPdf } from "md-to-pdf";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import * as os from "os";
|
|
5
|
+
export class PdfGenerator {
|
|
6
|
+
outputDir;
|
|
7
|
+
constructor(outputDir) {
|
|
8
|
+
this.outputDir = outputDir || path.join(os.homedir(), "mlc-reports");
|
|
9
|
+
this.ensureOutputDir();
|
|
10
|
+
}
|
|
11
|
+
ensureOutputDir() {
|
|
12
|
+
if (!fs.existsSync(this.outputDir)) {
|
|
13
|
+
fs.mkdirSync(this.outputDir, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Convert markdown content to PDF and save to file
|
|
18
|
+
*/
|
|
19
|
+
async generatePdf(markdown, options = {}) {
|
|
20
|
+
const { filename } = options;
|
|
21
|
+
const outputDir = options.outputDir || this.outputDir;
|
|
22
|
+
// Ensure output directory exists
|
|
23
|
+
if (!fs.existsSync(outputDir)) {
|
|
24
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
// Generate filename if not provided
|
|
27
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
28
|
+
const pdfFilename = filename || `mlc-report-${timestamp}.pdf`;
|
|
29
|
+
const outputPath = path.join(outputDir, pdfFilename);
|
|
30
|
+
const pdf = await mdToPdf({ content: markdown }, {
|
|
31
|
+
dest: outputPath,
|
|
32
|
+
pdf_options: {
|
|
33
|
+
format: "A4",
|
|
34
|
+
margin: {
|
|
35
|
+
top: "20mm",
|
|
36
|
+
right: "20mm",
|
|
37
|
+
bottom: "20mm",
|
|
38
|
+
left: "20mm",
|
|
39
|
+
},
|
|
40
|
+
printBackground: true,
|
|
41
|
+
},
|
|
42
|
+
stylesheet: [this.getStylesheet()],
|
|
43
|
+
body_class: ["mlc-report"],
|
|
44
|
+
});
|
|
45
|
+
if (!pdf || !pdf.filename) {
|
|
46
|
+
throw new Error("Failed to generate PDF");
|
|
47
|
+
}
|
|
48
|
+
return outputPath;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get CSS stylesheet for professional report styling
|
|
52
|
+
*/
|
|
53
|
+
getStylesheet() {
|
|
54
|
+
return `
|
|
55
|
+
body {
|
|
56
|
+
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
57
|
+
font-size: 11pt;
|
|
58
|
+
line-height: 1.6;
|
|
59
|
+
color: #333;
|
|
60
|
+
max-width: 100%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
h1 {
|
|
64
|
+
font-size: 24pt;
|
|
65
|
+
color: #1a365d;
|
|
66
|
+
border-bottom: 3px solid #2b6cb0;
|
|
67
|
+
padding-bottom: 10px;
|
|
68
|
+
margin-top: 0;
|
|
69
|
+
margin-bottom: 20px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
h2 {
|
|
73
|
+
font-size: 18pt;
|
|
74
|
+
color: #2c5282;
|
|
75
|
+
border-bottom: 1px solid #bee3f8;
|
|
76
|
+
padding-bottom: 8px;
|
|
77
|
+
margin-top: 30px;
|
|
78
|
+
margin-bottom: 15px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
h3 {
|
|
82
|
+
font-size: 14pt;
|
|
83
|
+
color: #2d3748;
|
|
84
|
+
margin-top: 25px;
|
|
85
|
+
margin-bottom: 10px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
h4 {
|
|
89
|
+
font-size: 12pt;
|
|
90
|
+
color: #4a5568;
|
|
91
|
+
margin-top: 20px;
|
|
92
|
+
margin-bottom: 8px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
p {
|
|
96
|
+
margin-bottom: 12px;
|
|
97
|
+
text-align: justify;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
table {
|
|
101
|
+
width: 100%;
|
|
102
|
+
border-collapse: collapse;
|
|
103
|
+
margin: 15px 0;
|
|
104
|
+
font-size: 10pt;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
th, td {
|
|
108
|
+
border: 1px solid #e2e8f0;
|
|
109
|
+
padding: 10px 12px;
|
|
110
|
+
text-align: left;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
th {
|
|
114
|
+
background-color: #edf2f7;
|
|
115
|
+
font-weight: 600;
|
|
116
|
+
color: #2d3748;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
tr:nth-child(even) {
|
|
120
|
+
background-color: #f7fafc;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
ul, ol {
|
|
124
|
+
margin-bottom: 15px;
|
|
125
|
+
padding-left: 25px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
li {
|
|
129
|
+
margin-bottom: 5px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
blockquote {
|
|
133
|
+
border-left: 4px solid #4299e1;
|
|
134
|
+
margin: 15px 0;
|
|
135
|
+
padding: 10px 20px;
|
|
136
|
+
background-color: #ebf8ff;
|
|
137
|
+
color: #2c5282;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
code {
|
|
141
|
+
background-color: #edf2f7;
|
|
142
|
+
padding: 2px 6px;
|
|
143
|
+
border-radius: 3px;
|
|
144
|
+
font-family: 'Consolas', 'Monaco', monospace;
|
|
145
|
+
font-size: 10pt;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
pre {
|
|
149
|
+
background-color: #2d3748;
|
|
150
|
+
color: #e2e8f0;
|
|
151
|
+
padding: 15px;
|
|
152
|
+
border-radius: 5px;
|
|
153
|
+
overflow-x: auto;
|
|
154
|
+
font-size: 10pt;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
pre code {
|
|
158
|
+
background-color: transparent;
|
|
159
|
+
padding: 0;
|
|
160
|
+
color: inherit;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
hr {
|
|
164
|
+
border: none;
|
|
165
|
+
border-top: 1px solid #e2e8f0;
|
|
166
|
+
margin: 25px 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
strong {
|
|
170
|
+
color: #1a202c;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
a {
|
|
174
|
+
color: #3182ce;
|
|
175
|
+
text-decoration: none;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
a:hover {
|
|
179
|
+
text-decoration: underline;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Report-specific styles */
|
|
183
|
+
.mlc-report {
|
|
184
|
+
padding: 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Warning/alert boxes */
|
|
188
|
+
.warning, [data-warning] {
|
|
189
|
+
background-color: #fffaf0;
|
|
190
|
+
border-left: 4px solid #ed8936;
|
|
191
|
+
padding: 10px 15px;
|
|
192
|
+
margin: 15px 0;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* Success boxes */
|
|
196
|
+
.success, [data-success] {
|
|
197
|
+
background-color: #f0fff4;
|
|
198
|
+
border-left: 4px solid #48bb78;
|
|
199
|
+
padding: 10px 15px;
|
|
200
|
+
margin: 15px 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/* Risk indicators */
|
|
204
|
+
.high-risk {
|
|
205
|
+
color: #c53030;
|
|
206
|
+
font-weight: 600;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.medium-risk {
|
|
210
|
+
color: #dd6b20;
|
|
211
|
+
font-weight: 600;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.low-risk {
|
|
215
|
+
color: #38a169;
|
|
216
|
+
font-weight: 600;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* Page break handling */
|
|
220
|
+
h1, h2 {
|
|
221
|
+
page-break-after: avoid;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
table, figure {
|
|
225
|
+
page-break-inside: avoid;
|
|
226
|
+
}
|
|
227
|
+
`;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Get the output directory path
|
|
231
|
+
*/
|
|
232
|
+
getOutputDir() {
|
|
233
|
+
return this.outputDir;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=pdf-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf-generator.js","sourceRoot":"","sources":["../../src/services/pdf-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAOzB,MAAM,OAAO,YAAY;IACf,SAAS,CAAS;IAE1B,YAAY,SAAkB;QAC5B,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;QACrE,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CACf,QAAgB,EAChB,UAA+B,EAAE;QAEjC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAC7B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC;QAEtD,iCAAiC;QACjC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QAED,oCAAoC;QACpC,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,QAAQ,IAAI,cAAc,SAAS,MAAM,CAAC;QAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAErD,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,EAAE,OAAO,EAAE,QAAQ,EAAE,EACrB;YACE,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE;gBACX,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE;oBACN,GAAG,EAAE,MAAM;oBACX,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,MAAM;oBACd,IAAI,EAAE,MAAM;iBACb;gBACD,eAAe,EAAE,IAAI;aACtB;YACD,UAAU,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YAClC,UAAU,EAAE,CAAC,YAAY,CAAC;SAC3B,CACF,CAAC;QAEF,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACK,aAAa;QACnB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6KN,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ApiClient } from "../services/api-client.js";
|
|
2
|
+
export interface AnalyzeCompanyInput {
|
|
3
|
+
pdf_path: string;
|
|
4
|
+
}
|
|
5
|
+
export interface AnalyzeCompanyResult {
|
|
6
|
+
task_id: number;
|
|
7
|
+
status: string;
|
|
8
|
+
message: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Analyze a company by uploading their annual report PDF
|
|
12
|
+
*/
|
|
13
|
+
export declare function analyzeCompany(apiClient: ApiClient, input: AnalyzeCompanyInput): Promise<AnalyzeCompanyResult>;
|
|
14
|
+
export declare const analyzeCompanySchema: {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: "object";
|
|
19
|
+
properties: {
|
|
20
|
+
pdf_path: {
|
|
21
|
+
type: string;
|
|
22
|
+
description: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
required: string[];
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/tools/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGtD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAc/B;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;CAehC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze a company by uploading their annual report PDF
|
|
3
|
+
*/
|
|
4
|
+
export async function analyzeCompany(apiClient, input) {
|
|
5
|
+
const { pdf_path } = input;
|
|
6
|
+
if (!pdf_path) {
|
|
7
|
+
throw new Error("pdf_path is required");
|
|
8
|
+
}
|
|
9
|
+
const response = await apiClient.uploadPdf(pdf_path);
|
|
10
|
+
return {
|
|
11
|
+
task_id: response.id,
|
|
12
|
+
status: response.status,
|
|
13
|
+
message: `Analysis task created successfully. Task ID: ${response.id}. Use get_report tool with this task_id to retrieve the PDF report once analysis is complete.`,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export const analyzeCompanySchema = {
|
|
17
|
+
name: "analyze_company",
|
|
18
|
+
description: "Upload a Chinese company annual report PDF and start MLC (Management Liability Coverage) analysis. Returns a task ID that can be used with get_report to retrieve the generated PDF report.",
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: "object",
|
|
21
|
+
properties: {
|
|
22
|
+
pdf_path: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Local file path to the company annual report PDF (e.g., /Users/name/Documents/company_report.pdf)",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ["pdf_path"],
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/tools/analyze.ts"],"names":[],"mappings":"AAaA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAoB,EACpB,KAA0B;IAE1B,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAE3B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,QAAQ,GAAuB,MAAM,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEzE,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,EAAE;QACpB,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,gDAAgD,QAAQ,CAAC,EAAE,+FAA+F;KACpK,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,6LAA6L;IAC/L,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,mGAAmG;aACtG;SACF;QACD,QAAQ,EAAE,CAAC,UAAU,CAAC;KACvB;CACF,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ApiClient } from "../services/api-client.js";
|
|
2
|
+
import { PdfGenerator } from "../services/pdf-generator.js";
|
|
3
|
+
export interface GetReportInput {
|
|
4
|
+
task_id: number;
|
|
5
|
+
wait_for_completion?: boolean;
|
|
6
|
+
output_filename?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GetReportResult {
|
|
9
|
+
pdf_path: string;
|
|
10
|
+
company_name: string | null;
|
|
11
|
+
is_listed: boolean | null;
|
|
12
|
+
is_soe: boolean | null;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get the PDF report for a completed analysis task
|
|
17
|
+
*/
|
|
18
|
+
export declare function getReport(apiClient: ApiClient, pdfGenerator: PdfGenerator, input: GetReportInput): Promise<GetReportResult>;
|
|
19
|
+
export declare const getReportSchema: {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: "object";
|
|
24
|
+
properties: {
|
|
25
|
+
task_id: {
|
|
26
|
+
type: string;
|
|
27
|
+
description: string;
|
|
28
|
+
};
|
|
29
|
+
wait_for_completion: {
|
|
30
|
+
type: string;
|
|
31
|
+
description: string;
|
|
32
|
+
default: boolean;
|
|
33
|
+
};
|
|
34
|
+
output_filename: {
|
|
35
|
+
type: string;
|
|
36
|
+
description: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
required: string[];
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=get-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-report.d.ts","sourceRoot":"","sources":["../../src/tools/get-report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAG5D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,eAAe,CAAC,CAmD1B;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;CAyB3B,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the PDF report for a completed analysis task
|
|
3
|
+
*/
|
|
4
|
+
export async function getReport(apiClient, pdfGenerator, input) {
|
|
5
|
+
const { task_id, wait_for_completion = true, output_filename } = input;
|
|
6
|
+
if (!task_id) {
|
|
7
|
+
throw new Error("task_id is required");
|
|
8
|
+
}
|
|
9
|
+
let task;
|
|
10
|
+
if (wait_for_completion) {
|
|
11
|
+
// Poll for completion
|
|
12
|
+
task = await apiClient.waitForCompletion(task_id, {
|
|
13
|
+
pollInterval: 5000,
|
|
14
|
+
timeout: 600000, // 10 minute timeout
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
task = await apiClient.getTaskStatus(task_id);
|
|
19
|
+
if (task.status !== "completed") {
|
|
20
|
+
throw new Error(`Task is not completed. Current status: ${task.status}. ` +
|
|
21
|
+
`Use wait_for_completion=true to wait for the task to finish.`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Fetch the markdown report
|
|
25
|
+
const markdownReport = await apiClient.getReport(task_id);
|
|
26
|
+
// Generate filename based on company name if available
|
|
27
|
+
let filename = output_filename;
|
|
28
|
+
if (!filename && task.company_name) {
|
|
29
|
+
const sanitizedName = task.company_name
|
|
30
|
+
.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_")
|
|
31
|
+
.substring(0, 50);
|
|
32
|
+
const timestamp = new Date().toISOString().split("T")[0];
|
|
33
|
+
filename = `${sanitizedName}_MLC_Report_${timestamp}.pdf`;
|
|
34
|
+
}
|
|
35
|
+
// Convert to PDF
|
|
36
|
+
const pdfPath = await pdfGenerator.generatePdf(markdownReport, {
|
|
37
|
+
filename,
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
pdf_path: pdfPath,
|
|
41
|
+
company_name: task.company_name,
|
|
42
|
+
is_listed: task.is_listed,
|
|
43
|
+
is_soe: task.is_soe,
|
|
44
|
+
message: `PDF report generated successfully and saved to: ${pdfPath}`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export const getReportSchema = {
|
|
48
|
+
name: "get_report",
|
|
49
|
+
description: "Retrieve the MLC analysis report for a completed task and convert it to PDF. The PDF will be saved to ~/mlc-reports/ directory. If the task is not yet complete, it will wait for completion (up to 10 minutes).",
|
|
50
|
+
inputSchema: {
|
|
51
|
+
type: "object",
|
|
52
|
+
properties: {
|
|
53
|
+
task_id: {
|
|
54
|
+
type: "number",
|
|
55
|
+
description: "The task ID returned by analyze_company",
|
|
56
|
+
},
|
|
57
|
+
wait_for_completion: {
|
|
58
|
+
type: "boolean",
|
|
59
|
+
description: "Whether to wait for the task to complete. Defaults to true. Set to false to return immediately if task is not complete.",
|
|
60
|
+
default: true,
|
|
61
|
+
},
|
|
62
|
+
output_filename: {
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "Optional custom filename for the PDF (without path). If not provided, filename will be generated from company name.",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
required: ["task_id"],
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=get-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-report.js","sourceRoot":"","sources":["../../src/tools/get-report.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,SAAoB,EACpB,YAA0B,EAC1B,KAAqB;IAErB,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAEvE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,IAAU,CAAC;IAEf,IAAI,mBAAmB,EAAE,CAAC;QACxB,sBAAsB;QACtB,IAAI,GAAG,MAAM,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE;YAChD,YAAY,EAAE,IAAI;YAClB,OAAO,EAAE,MAAM,EAAE,oBAAoB;SACtC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAE9C,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,0CAA0C,IAAI,CAAC,MAAM,IAAI;gBACvD,8DAA8D,CACjE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,4BAA4B;IAC5B,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAE1D,uDAAuD;IACvD,IAAI,QAAQ,GAAG,eAAe,CAAC;IAC/B,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACnC,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY;aACpC,OAAO,CAAC,4BAA4B,EAAE,GAAG,CAAC;aAC1C,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,QAAQ,GAAG,GAAG,aAAa,eAAe,SAAS,MAAM,CAAC;IAC5D,CAAC;IAED,iBAAiB;IACjB,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,cAAc,EAAE;QAC7D,QAAQ;KACT,CAAC,CAAC;IAEH,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,mDAAmD,OAAO,EAAE;KACtE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,kNAAkN;IACpN,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,yCAAyC;aACvD;YACD,mBAAmB,EAAE;gBACnB,IAAI,EAAE,SAAS;gBACf,WAAW,EACT,yHAAyH;gBAC3H,OAAO,EAAE,IAAI;aACd;YACD,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,qHAAqH;aACxH;SACF;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;CACF,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface TaskStep {
|
|
2
|
+
id: number;
|
|
3
|
+
task_id: number;
|
|
4
|
+
step_name: string;
|
|
5
|
+
status: "pending" | "running" | "completed" | "failed" | "skipped";
|
|
6
|
+
started_at: string | null;
|
|
7
|
+
completed_at: string | null;
|
|
8
|
+
error_message: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface Task {
|
|
11
|
+
id: number;
|
|
12
|
+
status: "pending" | "running" | "completed" | "failed";
|
|
13
|
+
company_name: string | null;
|
|
14
|
+
stock_code: string | null;
|
|
15
|
+
is_listed: boolean | null;
|
|
16
|
+
is_soe: boolean | null;
|
|
17
|
+
exchange: string | null;
|
|
18
|
+
pdf_path: string;
|
|
19
|
+
report_path: string | null;
|
|
20
|
+
error_message: string | null;
|
|
21
|
+
created_at: string;
|
|
22
|
+
updated_at: string;
|
|
23
|
+
steps: TaskStep[];
|
|
24
|
+
}
|
|
25
|
+
export interface CreateTaskResponse {
|
|
26
|
+
id: number;
|
|
27
|
+
status: string;
|
|
28
|
+
message: string;
|
|
29
|
+
}
|
|
30
|
+
export interface TaskListResponse {
|
|
31
|
+
tasks: Task[];
|
|
32
|
+
total: number;
|
|
33
|
+
page: number;
|
|
34
|
+
page_size: number;
|
|
35
|
+
}
|
|
36
|
+
export interface HealthResponse {
|
|
37
|
+
status: string;
|
|
38
|
+
database: string;
|
|
39
|
+
redis: string;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACvD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aig-risk-profiler-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for generating Management Liability Coverage (MLC) risk analysis reports from Chinese company annual report PDFs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"aig-risk-profiler-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"start": "node dist/index.js",
|
|
17
|
+
"dev": "tsx src/index.ts",
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"prepublishOnly": "npm run build"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"mcp",
|
|
23
|
+
"model-context-protocol",
|
|
24
|
+
"claude",
|
|
25
|
+
"ai",
|
|
26
|
+
"risk-analysis",
|
|
27
|
+
"mlc",
|
|
28
|
+
"insurance",
|
|
29
|
+
"annual-report",
|
|
30
|
+
"pdf",
|
|
31
|
+
"chinese-companies"
|
|
32
|
+
],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": ""
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
41
|
+
"md-to-pdf": "^5.2.4",
|
|
42
|
+
"axios": "^1.6.0",
|
|
43
|
+
"form-data": "^4.0.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^20.0.0",
|
|
47
|
+
"typescript": "^5.3.0",
|
|
48
|
+
"tsx": "^4.0.0"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=18.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|