@imenam/xls-reader 2.4.1 → 2.4.4
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 +170 -164
- package/dist/index.js +1 -4
- package/dist/logger.js +5 -6
- package/package.json +2 -5
package/README.md
CHANGED
|
@@ -1,164 +1,170 @@
|
|
|
1
|
-
# @imenam/xls-reader
|
|
2
|
-
|
|
3
|
-
An MCP (Model Context Protocol) server that lets AI agents read Excel files. It can list the sheets of a workbook and render any sheet as a Markdown table, with smart handling of empty rows, empty cells, and in-cell line breaks, plus a configurable size limit to keep responses LLM-friendly.
|
|
4
|
-
|
|
5
|
-
Supports `.xlsx`, `.xls`, `.ods` and `.csv` (anything [SheetJS](https://sheetjs.com/) can read).
|
|
6
|
-
|
|
7
|
-
## Where the file comes from
|
|
8
|
-
|
|
9
|
-
Both tools take the workbook either **by path** or **by content**:
|
|
10
|
-
|
|
11
|
-
- `file_path` — a path on the machine *running the server*. This is what a caller provides.
|
|
12
|
-
- `file_content` — the file itself, base64-encoded (a `data:…;base64,` prefix is accepted), with `file_name` to label the output.
|
|
13
|
-
|
|
14
|
-
At least one of the two is required. When both are given, `file_content` wins.
|
|
15
|
-
|
|
16
|
-
**When the server runs on another machine, the content is what must travel** — a path would point at a file the server cannot see. That translation is not the agent's job: the client-side relay does it. With [`@imenam/mcp-http-gateway`](https://www.npmjs.com/package/@imenam/mcp-http-gateway) in `--mcp` mode, the relay runs next to the agent, reads the file named by `file_path`, sends `file_content`, and hides `file_content` / `file_name` from the schema it publishes — so the agent only ever names a path. Enable it with `GATEWAY_INLINE_ROOTS`, which also confines *which* folders can be read; see that package's README.
|
|
17
|
-
|
|
18
|
-
Over stdio on a single machine, `file_path` is read directly and nothing else is needed.
|
|
19
|
-
|
|
20
|
-
## Tools
|
|
21
|
-
|
|
22
|
-
### `list_sheets`
|
|
23
|
-
|
|
24
|
-
Lists all sheet names (tabs) in a workbook.
|
|
25
|
-
|
|
26
|
-
| Parameter | Type | Required | Description |
|
|
27
|
-
|---|---|---|---|
|
|
28
|
-
| `file_path` | `string` | ⚠️ | Path to the Excel file. Resolved on the server, or read by the relay (see above) |
|
|
29
|
-
| `file_content` | `string` | ⚠️ | Base64 content of the file. Normally filled in by the relay, not by the agent |
|
|
30
|
-
| `file_name` | `string` | ❌ | Original file name, used only for labelling. Filled in with `file_content` |
|
|
31
|
-
|
|
32
|
-
Returns the sheet names, one per line.
|
|
33
|
-
|
|
34
|
-
### `get_sheet`
|
|
35
|
-
|
|
36
|
-
Reads a sheet and returns its content as a Markdown table.
|
|
37
|
-
|
|
38
|
-
| Parameter | Type | Required | Description |
|
|
39
|
-
|---|---|---|---|
|
|
40
|
-
| `file_path` | `string` | ⚠️ | Path to the Excel file. Resolved on the server, or read by the relay (see above) |
|
|
41
|
-
| `file_content` | `string` | ⚠️ | Base64 content of the file. Normally filled in by the relay, not by the agent |
|
|
42
|
-
| `file_name` | `string` | ❌ | Original file name, used only for labelling. Filled in with `file_content` |
|
|
43
|
-
| `sheet_name` | `string` | ✅ | Name of the sheet to read |
|
|
44
|
-
| `format` | `"markdown" \| "json"` | ❌ | Output format (default: `markdown`) |
|
|
45
|
-
| `cell_budget` | `number` | ❌ | Maximum number of cells to return (cols × rows). Default: `2000` |
|
|
46
|
-
| `max_cols` | `number` | ❌ | Override the maximum number of columns |
|
|
47
|
-
| `max_rows` | `number` | ❌ | Override the maximum number of rows |
|
|
48
|
-
| `header_row` | `boolean` | ❌ | Treat the first row as a column header (default: `true`) |
|
|
49
|
-
|
|
50
|
-
#### Smart content handling
|
|
51
|
-
|
|
52
|
-
- **Empty rows are section separators.** A fully empty row closes the current table and starts a new one; when `header_row` is enabled, the header is repeated on each section.
|
|
53
|
-
- **Empty cells are kept as blanks** so columns stay aligned.
|
|
54
|
-
- **In-cell line breaks** are converted to a literal `\n` so they don't break the Markdown table row.
|
|
55
|
-
- **Dates and booleans** are rendered as readable text rather than Excel serial numbers.
|
|
56
|
-
|
|
57
|
-
#### Output formats
|
|
58
|
-
|
|
59
|
-
With `format: "markdown"` (default) you get one Markdown table per section.
|
|
60
|
-
|
|
61
|
-
With `format: "json"` you get a structured object — better when the agent needs to *process* the data rather than read it. Native types are preserved (numbers, booleans, dates as ISO strings) and real line breaks are kept:
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
{
|
|
65
|
-
"sheet": "Feuille1",
|
|
66
|
-
"truncated": false,
|
|
67
|
-
"groups": [
|
|
68
|
-
[
|
|
69
|
-
{ "Nom": "Dupont", "Prénom": "Jean", "Age": 42 },
|
|
70
|
-
{ "Nom": "Martin", "Age": 35 }
|
|
71
|
-
]
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
- `groups` is an array of sections (one per block separated by an empty row).
|
|
77
|
-
- With `header_row: true`, each row is an **object** keyed by column name; **empty cells are omitted**.
|
|
78
|
-
- With `header_row: false`, each row is an **array** of values (empty cells become `null`).
|
|
79
|
-
- When data is truncated, `truncated` is `true` and a `note` field explains what was omitted.
|
|
80
|
-
|
|
81
|
-
To export without any size limit, use [`export_workbook`](#export_workbook), which writes a JSON file instead of returning it.
|
|
82
|
-
|
|
83
|
-
#### Size limit
|
|
84
|
-
|
|
85
|
-
By default the response is capped at `cell_budget = 2000` cells (`cols × rows`). With 10 columns you get ~200 rows; with 20 columns, ~100 rows. When data is truncated, a warning is appended telling you how much was omitted. Override with `cell_budget`, `max_cols`, or `max_rows` to read more (or less).
|
|
86
|
-
|
|
87
|
-
### `export_workbook`
|
|
88
|
-
|
|
89
|
-
Exports a workbook as a JSON file, with **no size limit**, and writes it **on the agent machine**. Use it when the data is too large to return inline. By default the entire workbook is exported; provide `sheet_name` to export only one sheet.
|
|
90
|
-
|
|
91
|
-
| Parameter | Type | Required | Description |
|
|
92
|
-
|---|---|---|---|
|
|
93
|
-
| `file_path` | `string` | ⚠️ | Path to the Excel file. Resolved on the server, or read by the relay (see above) |
|
|
94
|
-
| `file_content` | `string` | ⚠️ | Base64 content of the file. Normally filled in by the relay, not by the agent |
|
|
95
|
-
| `file_name` | `string` | ❌ | Original file name, used only for labelling. Filled in with `file_content` |
|
|
96
|
-
| `sheet_name` | `string` | ❌ | Omit to export the whole workbook, or set it to export only that sheet |
|
|
97
|
-
| `header_row` | `boolean` | ❌ | Treat the first row as a column header (default: `true`) |
|
|
98
|
-
| `destination_path` | `string` | ✅ | **Absolute directory** on the agent machine. Created if missing |
|
|
99
|
-
| `filename` | `string` | ✅ | Name the exported file gets there, e.g. `data.json`. No path separators |
|
|
100
|
-
| `destination_overwrite` | `boolean` | ❌ | Replace the destination file if it exists (default: `false`) |
|
|
101
|
-
| `destination_relay` | `boolean` | ❌ | Filled in by the relay, never by the agent |
|
|
102
|
-
|
|
103
|
-
The exported file never passes through the conversation. When this MCP runs next to the agent (stdio), it writes the file itself. Behind [`@imenam/mcp-http-gateway`](https://www.npmjs.com/package/@imenam/mcp-http-gateway) it runs on the gateway's machine and cannot reach the agent's disk: it then returns the bytes, and the relay — which *does* run on the agent machine — writes them at `destination_path`. The relay keeps that path to itself and never forwards it, which is why the tool schema declares it optional; the tool rejects a call that lacks it when it has to write the file itself. That path requires `GATEWAY_INLINE_WRITE_ROOTS` in the relay's `env` block; without it the call fails explicitly rather than dropping the file on the wrong machine.
|
|
104
|
-
|
|
105
|
-
The file content is:
|
|
106
|
-
|
|
107
|
-
```json
|
|
108
|
-
{
|
|
109
|
-
"file": "data.xlsx",
|
|
110
|
-
"sheets": [
|
|
111
|
-
{ "sheet": "Feuille1", "groups": [ /* …same shape as json… */ ] },
|
|
112
|
-
{ "sheet": "Feuille2", "groups": [ /* … */ ] }
|
|
113
|
-
]
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## Installation
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
npm install -g @imenam/xls-reader
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
Or use it directly with `npx`:
|
|
124
|
-
|
|
125
|
-
```json
|
|
126
|
-
{
|
|
127
|
-
"xls-reader": {
|
|
128
|
-
"command": "npx",
|
|
129
|
-
"args": ["-y", "@imenam/xls-reader"]
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
Or point to a local build:
|
|
135
|
-
|
|
136
|
-
```json
|
|
137
|
-
{
|
|
138
|
-
"xls-reader": {
|
|
139
|
-
"command": "node",
|
|
140
|
-
"args": ["/absolute/path/to/xls-reader/dist/index.js"]
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Configuration
|
|
146
|
-
|
|
147
|
-
No environment variables are required. Optionally, set `MCP_LOG_DIR` to change where logs are written (default:
|
|
148
|
-
|
|
149
|
-
```env
|
|
150
|
-
# .env
|
|
151
|
-
MCP_LOG_DIR=/absolute/path/to/logs
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## Development
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
npm install
|
|
158
|
-
npm run build # compile TypeScript to dist/
|
|
159
|
-
npm run dev # run from source with tsx
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
##
|
|
163
|
-
|
|
164
|
-
|
|
1
|
+
# @imenam/xls-reader
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server that lets AI agents read Excel files. It can list the sheets of a workbook and render any sheet as a Markdown table, with smart handling of empty rows, empty cells, and in-cell line breaks, plus a configurable size limit to keep responses LLM-friendly.
|
|
4
|
+
|
|
5
|
+
Supports `.xlsx`, `.xls`, `.ods` and `.csv` (anything [SheetJS](https://sheetjs.com/) can read).
|
|
6
|
+
|
|
7
|
+
## Where the file comes from
|
|
8
|
+
|
|
9
|
+
Both tools take the workbook either **by path** or **by content**:
|
|
10
|
+
|
|
11
|
+
- `file_path` — a path on the machine *running the server*. This is what a caller provides.
|
|
12
|
+
- `file_content` — the file itself, base64-encoded (a `data:…;base64,` prefix is accepted), with `file_name` to label the output.
|
|
13
|
+
|
|
14
|
+
At least one of the two is required. When both are given, `file_content` wins.
|
|
15
|
+
|
|
16
|
+
**When the server runs on another machine, the content is what must travel** — a path would point at a file the server cannot see. That translation is not the agent's job: the client-side relay does it. With [`@imenam/mcp-http-gateway`](https://www.npmjs.com/package/@imenam/mcp-http-gateway) in `--mcp` mode, the relay runs next to the agent, reads the file named by `file_path`, sends `file_content`, and hides `file_content` / `file_name` from the schema it publishes — so the agent only ever names a path. Enable it with `GATEWAY_INLINE_ROOTS`, which also confines *which* folders can be read; see that package's README.
|
|
17
|
+
|
|
18
|
+
Over stdio on a single machine, `file_path` is read directly and nothing else is needed.
|
|
19
|
+
|
|
20
|
+
## Tools
|
|
21
|
+
|
|
22
|
+
### `list_sheets`
|
|
23
|
+
|
|
24
|
+
Lists all sheet names (tabs) in a workbook.
|
|
25
|
+
|
|
26
|
+
| Parameter | Type | Required | Description |
|
|
27
|
+
|---|---|---|---|
|
|
28
|
+
| `file_path` | `string` | ⚠️ | Path to the Excel file. Resolved on the server, or read by the relay (see above) |
|
|
29
|
+
| `file_content` | `string` | ⚠️ | Base64 content of the file. Normally filled in by the relay, not by the agent |
|
|
30
|
+
| `file_name` | `string` | ❌ | Original file name, used only for labelling. Filled in with `file_content` |
|
|
31
|
+
|
|
32
|
+
Returns the sheet names, one per line.
|
|
33
|
+
|
|
34
|
+
### `get_sheet`
|
|
35
|
+
|
|
36
|
+
Reads a sheet and returns its content as a Markdown table.
|
|
37
|
+
|
|
38
|
+
| Parameter | Type | Required | Description |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `file_path` | `string` | ⚠️ | Path to the Excel file. Resolved on the server, or read by the relay (see above) |
|
|
41
|
+
| `file_content` | `string` | ⚠️ | Base64 content of the file. Normally filled in by the relay, not by the agent |
|
|
42
|
+
| `file_name` | `string` | ❌ | Original file name, used only for labelling. Filled in with `file_content` |
|
|
43
|
+
| `sheet_name` | `string` | ✅ | Name of the sheet to read |
|
|
44
|
+
| `format` | `"markdown" \| "json"` | ❌ | Output format (default: `markdown`) |
|
|
45
|
+
| `cell_budget` | `number` | ❌ | Maximum number of cells to return (cols × rows). Default: `2000` |
|
|
46
|
+
| `max_cols` | `number` | ❌ | Override the maximum number of columns |
|
|
47
|
+
| `max_rows` | `number` | ❌ | Override the maximum number of rows |
|
|
48
|
+
| `header_row` | `boolean` | ❌ | Treat the first row as a column header (default: `true`) |
|
|
49
|
+
|
|
50
|
+
#### Smart content handling
|
|
51
|
+
|
|
52
|
+
- **Empty rows are section separators.** A fully empty row closes the current table and starts a new one; when `header_row` is enabled, the header is repeated on each section.
|
|
53
|
+
- **Empty cells are kept as blanks** so columns stay aligned.
|
|
54
|
+
- **In-cell line breaks** are converted to a literal `\n` so they don't break the Markdown table row.
|
|
55
|
+
- **Dates and booleans** are rendered as readable text rather than Excel serial numbers.
|
|
56
|
+
|
|
57
|
+
#### Output formats
|
|
58
|
+
|
|
59
|
+
With `format: "markdown"` (default) you get one Markdown table per section.
|
|
60
|
+
|
|
61
|
+
With `format: "json"` you get a structured object — better when the agent needs to *process* the data rather than read it. Native types are preserved (numbers, booleans, dates as ISO strings) and real line breaks are kept:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"sheet": "Feuille1",
|
|
66
|
+
"truncated": false,
|
|
67
|
+
"groups": [
|
|
68
|
+
[
|
|
69
|
+
{ "Nom": "Dupont", "Prénom": "Jean", "Age": 42 },
|
|
70
|
+
{ "Nom": "Martin", "Age": 35 }
|
|
71
|
+
]
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- `groups` is an array of sections (one per block separated by an empty row).
|
|
77
|
+
- With `header_row: true`, each row is an **object** keyed by column name; **empty cells are omitted**.
|
|
78
|
+
- With `header_row: false`, each row is an **array** of values (empty cells become `null`).
|
|
79
|
+
- When data is truncated, `truncated` is `true` and a `note` field explains what was omitted.
|
|
80
|
+
|
|
81
|
+
To export without any size limit, use [`export_workbook`](#export_workbook), which writes a JSON file instead of returning it.
|
|
82
|
+
|
|
83
|
+
#### Size limit
|
|
84
|
+
|
|
85
|
+
By default the response is capped at `cell_budget = 2000` cells (`cols × rows`). With 10 columns you get ~200 rows; with 20 columns, ~100 rows. When data is truncated, a warning is appended telling you how much was omitted. Override with `cell_budget`, `max_cols`, or `max_rows` to read more (or less).
|
|
86
|
+
|
|
87
|
+
### `export_workbook`
|
|
88
|
+
|
|
89
|
+
Exports a workbook as a JSON file, with **no size limit**, and writes it **on the agent machine**. Use it when the data is too large to return inline. By default the entire workbook is exported; provide `sheet_name` to export only one sheet.
|
|
90
|
+
|
|
91
|
+
| Parameter | Type | Required | Description |
|
|
92
|
+
|---|---|---|---|
|
|
93
|
+
| `file_path` | `string` | ⚠️ | Path to the Excel file. Resolved on the server, or read by the relay (see above) |
|
|
94
|
+
| `file_content` | `string` | ⚠️ | Base64 content of the file. Normally filled in by the relay, not by the agent |
|
|
95
|
+
| `file_name` | `string` | ❌ | Original file name, used only for labelling. Filled in with `file_content` |
|
|
96
|
+
| `sheet_name` | `string` | ❌ | Omit to export the whole workbook, or set it to export only that sheet |
|
|
97
|
+
| `header_row` | `boolean` | ❌ | Treat the first row as a column header (default: `true`) |
|
|
98
|
+
| `destination_path` | `string` | ✅ | **Absolute directory** on the agent machine. Created if missing |
|
|
99
|
+
| `filename` | `string` | ✅ | Name the exported file gets there, e.g. `data.json`. No path separators |
|
|
100
|
+
| `destination_overwrite` | `boolean` | ❌ | Replace the destination file if it exists (default: `false`) |
|
|
101
|
+
| `destination_relay` | `boolean` | ❌ | Filled in by the relay, never by the agent |
|
|
102
|
+
|
|
103
|
+
The exported file never passes through the conversation. When this MCP runs next to the agent (stdio), it writes the file itself. Behind [`@imenam/mcp-http-gateway`](https://www.npmjs.com/package/@imenam/mcp-http-gateway) it runs on the gateway's machine and cannot reach the agent's disk: it then returns the bytes, and the relay — which *does* run on the agent machine — writes them at `destination_path`. The relay keeps that path to itself and never forwards it, which is why the tool schema declares it optional; the tool rejects a call that lacks it when it has to write the file itself. That path requires `GATEWAY_INLINE_WRITE_ROOTS` in the relay's `env` block; without it the call fails explicitly rather than dropping the file on the wrong machine.
|
|
104
|
+
|
|
105
|
+
The file content is:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"file": "data.xlsx",
|
|
110
|
+
"sheets": [
|
|
111
|
+
{ "sheet": "Feuille1", "groups": [ /* …same shape as json… */ ] },
|
|
112
|
+
{ "sheet": "Feuille2", "groups": [ /* … */ ] }
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Installation
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm install -g @imenam/xls-reader
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Or use it directly with `npx`:
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"xls-reader": {
|
|
128
|
+
"command": "npx",
|
|
129
|
+
"args": ["-y", "@imenam/xls-reader"]
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Or point to a local build:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"xls-reader": {
|
|
139
|
+
"command": "node",
|
|
140
|
+
"args": ["/absolute/path/to/xls-reader/dist/index.js"]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Configuration
|
|
146
|
+
|
|
147
|
+
No environment variables are required. Optionally, set `MCP_LOG_DIR` to change where logs are written (default: `.xls-reader/logs` in the home directory of the user running the server). When the log file cannot be written, each log line is reported on stderr as `Critical: Failed to write to log file <path>: <reason>` and the server keeps running.
|
|
148
|
+
|
|
149
|
+
```env
|
|
150
|
+
# .env
|
|
151
|
+
MCP_LOG_DIR=/absolute/path/to/logs
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm install
|
|
158
|
+
npm run build # compile TypeScript to dist/
|
|
159
|
+
npm run dev # run from source with tsx
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Publication
|
|
163
|
+
|
|
164
|
+
Chaque push sur `master`, merge de pull request compris, publie une nouvelle version de `@imenam/xls-reader` sur npm (`.github/workflows/publish.yml`) : `npm ci` et build, puis `npm version patch`, dont le commit et le tag sont poussés sur `master`, et `npm publish`. La publication passe par le trusted publishing de npm (OIDC, sans token), avec attestation de provenance. Un échec du build arrête le workflow avant la montée de version.
|
|
165
|
+
|
|
166
|
+
Sur npmjs.com, le paquet déclare ce workflow comme publieur de confiance (Settings → Trusted publishing → GitHub Actions : `Matthieu-Pesnot-Pin`, `xls-reader`, `publish.yml`, avec `npm publish` dans les actions autorisées). Le commit de version est poussé avec `GITHUB_TOKEN` : si `master` est protégée, la règle doit autoriser GitHub Actions à y pousser.
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { listSheets, readSheet, readWorkbook } from "./excel.js";
|
|
|
10
10
|
import { deliverFile, RELAY_SHAPE_DESCRIPTIONS } from "./relay.js";
|
|
11
11
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
12
|
const rootDir = path.resolve(__dirname, "..");
|
|
13
|
-
dotenv.config({ path: path.join(rootDir, ".env"), override: true });
|
|
13
|
+
dotenv.config({ path: path.join(rootDir, ".env"), override: true, quiet: true });
|
|
14
14
|
setupLogging("MASTER");
|
|
15
15
|
const server = new McpServer({
|
|
16
16
|
name: "xls-reader",
|
|
@@ -107,9 +107,6 @@ server.tool("get_sheet", [
|
|
|
107
107
|
}
|
|
108
108
|
});
|
|
109
109
|
// ─── export_workbook ──────────────────────────────────────────────────────────
|
|
110
|
-
// L'export est un outil à part, et non un `format` de get_sheet : le relais rend
|
|
111
|
-
// obligatoire tout `<x>_path` dont il voit la paire, donc porter `destination_path` dans
|
|
112
|
-
// get_sheet forcerait une destination sur chaque simple lecture de feuille.
|
|
113
110
|
server.tool("export_workbook", [
|
|
114
111
|
"Export an Excel workbook as a JSON file written on the agent machine, with no size limit.",
|
|
115
112
|
"Exports the whole workbook, or only sheet_name when provided.",
|
package/dist/logger.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
+
import os from "os";
|
|
2
3
|
import path from "path";
|
|
3
4
|
let currentPrefix = "";
|
|
4
5
|
export function logToFile(message, prefix = "") {
|
|
5
|
-
const
|
|
6
|
-
? "C:\\var\\log\\xls-reader"
|
|
7
|
-
: "/var/log/xls-reader";
|
|
8
|
-
const logDir = process.env.MCP_LOG_DIR ?? defaultLogDir;
|
|
6
|
+
const logDir = process.env.MCP_LOG_DIR ?? path.join(os.homedir(), ".xls-reader", "logs");
|
|
9
7
|
const logFile = path.join(logDir, "server.log");
|
|
10
8
|
const now = new Date().toLocaleString("fr-FR", {
|
|
11
9
|
year: "numeric",
|
|
@@ -24,8 +22,9 @@ export function logToFile(message, prefix = "") {
|
|
|
24
22
|
}
|
|
25
23
|
fs.appendFileSync(logFile, logEntry);
|
|
26
24
|
}
|
|
27
|
-
catch {
|
|
28
|
-
|
|
25
|
+
catch (error) {
|
|
26
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
27
|
+
process.stderr.write(`Critical: Failed to write to log file ${logFile}: ${reason}\n`);
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
export function setupLogging(prefix) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imenam/xls-reader",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.4",
|
|
4
4
|
"description": "MCP server that lets AI agents read Excel files: list sheets and render any sheet as a Markdown table.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,10 +14,7 @@
|
|
|
14
14
|
"build": "tsc",
|
|
15
15
|
"start": "node dist/index.js",
|
|
16
16
|
"dev": "tsx src/index.ts",
|
|
17
|
-
"prepublishOnly": "npm run build"
|
|
18
|
-
"release:patch": "npm version patch && npm publish --access public && git push origin master --follow-tags",
|
|
19
|
-
"release:minor": "npm version minor && npm publish --access public && git push origin master --follow-tags",
|
|
20
|
-
"release:major": "npm version major && npm publish --access public && git push origin master --follow-tags"
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
21
18
|
},
|
|
22
19
|
"keywords": [
|
|
23
20
|
"mcp",
|