ptn-mcp 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ import https from "https";
2
+ import axios from "axios";
3
+ const agents = {};
4
+ function envTlsInsecure() {
5
+ return process.env.PTN_TLS_INSECURE === "1" || process.env.PTN_TLS_INSECURE === "true";
6
+ }
7
+ /**
8
+ * HTTPS agent for api.ptn.gob.ar.
9
+ * Strict verification by default. Use PTN_TLS_INSECURE=1 only when your OS/proxy
10
+ * cannot validate the PTN certificate chain.
11
+ */
12
+ export function getPtnHttpsAgent(insecure = envTlsInsecure()) {
13
+ const key = insecure ? "insecure" : "strict";
14
+ if (!agents[key]) {
15
+ agents[key] = new https.Agent({ rejectUnauthorized: !insecure });
16
+ }
17
+ return agents[key];
18
+ }
19
+ function isTlsVerificationError(error) {
20
+ if (!axios.isAxiosError(error))
21
+ return false;
22
+ const code = error.code ?? "";
23
+ const message = error.message ?? "";
24
+ return (code === "UNABLE_TO_VERIFY_LEAF_SIGNATURE" ||
25
+ code === "UNABLE_TO_VERIFY_CERT_SIGNATURE" ||
26
+ code === "CERT_HAS_EXPIRED" ||
27
+ message.includes("unable to verify") ||
28
+ message.includes("certificate"));
29
+ }
30
+ let tlsFallbackWarned = false;
31
+ /**
32
+ * POST helper: strict TLS first; one retry without verification only on cert errors.
33
+ */
34
+ export async function ptnPost(url, body, config = {}) {
35
+ const base = {
36
+ ...config,
37
+ headers: {
38
+ "Content-Type": "application/json",
39
+ Accept: "application/json",
40
+ ...config.headers,
41
+ },
42
+ timeout: config.timeout ?? 45000,
43
+ };
44
+ if (envTlsInsecure()) {
45
+ const response = await axios.post(url, body, {
46
+ ...base,
47
+ httpsAgent: getPtnHttpsAgent(true),
48
+ });
49
+ return response.data;
50
+ }
51
+ try {
52
+ const response = await axios.post(url, body, {
53
+ ...base,
54
+ httpsAgent: getPtnHttpsAgent(false),
55
+ });
56
+ return response.data;
57
+ }
58
+ catch (error) {
59
+ if (!isTlsVerificationError(error))
60
+ throw error;
61
+ if (!tlsFallbackWarned) {
62
+ tlsFallbackWarned = true;
63
+ console.error("PTN MCP: TLS verification failed; retrying without certificate check. " +
64
+ "Set PTN_TLS_INSECURE=1 to use insecure TLS from the start.");
65
+ }
66
+ const response = await axios.post(url, body, {
67
+ ...base,
68
+ httpsAgent: getPtnHttpsAgent(true),
69
+ });
70
+ return response.data;
71
+ }
72
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "ptn-mcp",
3
+ "version": "1.3.0",
4
+ "description": "PTN-MCP — MCP Server para buscar y extraer dictámenes de la Procuración del Tesoro de la Nación (busquedadictamenes.ptn.gob.ar). 22 tools especializadas + 3 prompts para abogados.",
5
+ "type": "module",
6
+ "main": "build/index.js",
7
+ "bin": {
8
+ "ptn-mcp": "./build/index.js"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/voftec/ptn-mcp.git"
13
+ },
14
+ "homepage": "https://github.com/voftec/ptn-mcp#readme",
15
+ "files": [
16
+ "build",
17
+ "README.md",
18
+ "TOOLS.md",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "dev": "tsc -w",
24
+ "start": "node build/index.js",
25
+ "test": "npm run build && node --test test/**/*.test.mjs",
26
+ "test:smoke": "npm run build && node scripts/smoke-mcp.mjs",
27
+ "verify:utf8": "node scripts/verify-utf8.mjs"
28
+ },
29
+ "keywords": [
30
+ "mcp",
31
+ "model-context-protocol",
32
+ "argentina",
33
+ "ptn",
34
+ "procuracion-tesoro",
35
+ "dictamenes",
36
+ "legal",
37
+ "scraper",
38
+ "voftec"
39
+ ],
40
+ "author": "Voftec",
41
+ "license": "MIT",
42
+ "dependencies": {
43
+ "@modelcontextprotocol/sdk": "^1.5.0",
44
+ "axios": "^1.7.0",
45
+ "zod": "^3.23.0"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^20.0.0",
49
+ "typescript": "^5.4.5"
50
+ }
51
+ }