@imenam/simple-scraper 1.0.18 → 1.0.20
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 +17 -0
- package/dist/env-precedence.js +51 -0
- package/dist/index.js +8 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -90,6 +90,23 @@ PUPPETEER_DEVICE_SCALE_FACTOR=1
|
|
|
90
90
|
# APP_GROUP=Scraping
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
### The process environment wins over `.env`
|
|
94
|
+
|
|
95
|
+
Any variable already set in the environment of the process that starts this MCP
|
|
96
|
+
(a shell `export`, a `claude_desktop_config.json` `env` block, or a supervisor
|
|
97
|
+
such as `@imenam/mcp-gateway-manager`) **takes precedence over the same key in
|
|
98
|
+
this repository's `.env`**. This is dotenv's default behaviour, and the usual
|
|
99
|
+
Unix convention: the caller wins.
|
|
100
|
+
|
|
101
|
+
The `.env` is still reloaded on the fly — the GUI writes to it and the change is
|
|
102
|
+
picked up without restarting the server — but that reload can no longer clobber
|
|
103
|
+
what the caller injected. Concretely, an `APP_GROUP=Scraping` line in this
|
|
104
|
+
`.env` no longer overrides an `APP_GROUP` passed in by a supervisor; it only
|
|
105
|
+
applies when nobody passed one.
|
|
106
|
+
|
|
107
|
+
To change a variable that the caller provides, change it where the caller sets
|
|
108
|
+
it; editing `.env` will have no effect on that key.
|
|
109
|
+
|
|
93
110
|
## Usage with Claude Desktop
|
|
94
111
|
|
|
95
112
|
Add the following to your `claude_desktop_config.json`. Full example with all available options:
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chargement du `.env` du dépôt, sans jamais écraser l'environnement du process.
|
|
3
|
+
*
|
|
4
|
+
* ## Le problème
|
|
5
|
+
*
|
|
6
|
+
* Ce MCP rechargeait son `.env` avec `dotenv.config({ override: true })`, au
|
|
7
|
+
* démarrage et à chaque `reloadEnv` du `GuiLauncher`. C'est délibéré : la GUI
|
|
8
|
+
* écrit dans le `.env` et le code relit la valeur sans redémarrer le process.
|
|
9
|
+
* Sans `override`, dotenv ignore toute clé déjà présente dans `process.env` —
|
|
10
|
+
* donc la deuxième lecture ne verrait jamais rien changer.
|
|
11
|
+
*
|
|
12
|
+
* Mais `override: true` écrase **aussi** ce qu'un superviseur a injecté. Quand
|
|
13
|
+
* le hub `mcp-gateway-manager` lance ce MCP en lui passant `APP_GROUP`,
|
|
14
|
+
* `PROXY_URL` ou `APP_PATH_PREFIX` dans son bloc `env`, le `.env` du dépôt
|
|
15
|
+
* reprenait la main et l'injection échouait **silencieusement**.
|
|
16
|
+
*
|
|
17
|
+
* ## La règle appliquée ici
|
|
18
|
+
*
|
|
19
|
+
* Une variable **déjà présente dans l'environnement du process au démarrage**
|
|
20
|
+
* l'emporte sur le `.env` du dépôt — c'est le comportement par défaut de dotenv,
|
|
21
|
+
* et la convention de tout l'écosystème Unix : l'appelant gagne.
|
|
22
|
+
*
|
|
23
|
+
* L'`override` n'est pas supprimé pour autant, il est **restreint** : il reste
|
|
24
|
+
* entier pour toutes les variables que le process n'a pas héritées, c'est-à-dire
|
|
25
|
+
* exactement celles que l'interface graphique édite dans le `.env`. On ne perd
|
|
26
|
+
* donc pas le rechargement à chaud, on l'empêche seulement de piétiner
|
|
27
|
+
* l'appelant.
|
|
28
|
+
*
|
|
29
|
+
* L'instantané est pris à l'évaluation de ce module : il doit donc être importé
|
|
30
|
+
* avant tout appel à `dotenv.config`.
|
|
31
|
+
*/
|
|
32
|
+
import dotenv from 'dotenv';
|
|
33
|
+
/** Environnement du process **avant** tout chargement de `.env`. */
|
|
34
|
+
const inherited = Object.freeze(Object.fromEntries(Object.entries(process.env).filter((entry) => typeof entry[1] === 'string')));
|
|
35
|
+
/** La variable vient-elle de l'appelant (superviseur, shell) plutôt que du `.env` ? */
|
|
36
|
+
export function isInheritedFromProcess(key) {
|
|
37
|
+
return Object.prototype.hasOwnProperty.call(inherited, key);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Charge un fichier `.env` en écrasant les valeurs déjà lues depuis ce fichier,
|
|
41
|
+
* mais **jamais** celles héritées de l'environnement du process.
|
|
42
|
+
*/
|
|
43
|
+
export function loadEnvFile(options) {
|
|
44
|
+
// Le résultat peut être absent quand dotenv est remplacé par un test double.
|
|
45
|
+
const result = dotenv.config({ ...options, override: true });
|
|
46
|
+
for (const key of Object.keys(result?.parsed ?? {})) {
|
|
47
|
+
const value = inherited[key];
|
|
48
|
+
if (value !== undefined)
|
|
49
|
+
process.env[key] = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
-
|
|
4
|
+
// Importé AVANT tout appel à dotenv : ce module prend l'instantané de
|
|
5
|
+
// l'environnement hérité du process, qui doit primer sur le `.env` du dépôt.
|
|
6
|
+
import { loadEnvFile } from './env-precedence.js';
|
|
5
7
|
import fs from 'fs';
|
|
6
8
|
import path from 'path';
|
|
7
9
|
import { fileURLToPath } from 'url';
|
|
@@ -21,11 +23,14 @@ if (process.argv.slice(2).includes('--claude-setup-mcp')) {
|
|
|
21
23
|
const { runSetupMcp } = await import('./cli/setup-mcp.js');
|
|
22
24
|
process.exit(runSetupMcp({ cwd: process.cwd(), force: process.argv.slice(2).includes('--force') }));
|
|
23
25
|
}
|
|
24
|
-
|
|
26
|
+
// `override` restreint : la GUI peut toujours éditer le `.env` et voir l'effet
|
|
27
|
+
// sans redémarrage, mais une variable injectée par un superviseur (`PROXY_URL`,
|
|
28
|
+
// `APP_GROUP`, `APP_PATH_PREFIX`…) reste intacte. Voir ./env-precedence.ts.
|
|
29
|
+
loadEnvFile({ path: envPath });
|
|
25
30
|
setupLogging('MASTER');
|
|
26
31
|
const launcher = new GuiLauncher({
|
|
27
32
|
guiPath: path.join(__dirname, 'gui.js'),
|
|
28
|
-
reloadEnv: () =>
|
|
33
|
+
reloadEnv: () => loadEnvFile({ path: envPath }),
|
|
29
34
|
onMessage: (msg) => {
|
|
30
35
|
if (msg.type === 'STOP') {
|
|
31
36
|
process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imenam/simple-scraper",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"description": "MCP server for web scraping and JavaScript execution using Puppeteer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"node": ">=18.0.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@imenam/mcp-gui-interface": "^1.0.
|
|
38
|
+
"@imenam/mcp-gui-interface": "^1.0.12",
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
40
40
|
"body-parser": "^2.2.2",
|
|
41
41
|
"dotenv": "^17.3.1",
|