@apogea/apports-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.
Files changed (3) hide show
  1. package/README.md +20 -0
  2. package/bin/cli.js +105 -0
  3. package/package.json +27 -0
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # @apports/mcp-cli
2
+
3
+ Puente de línea de comandos para conectar clientes MCP locales (Claude Desktop) con el servidor backend de Apports.
4
+
5
+ ## Uso con npx
6
+
7
+ ```json
8
+ {
9
+ "mcpServers": {
10
+ "apports": {
11
+ "command": "npx",
12
+ "args": ["-y", "@apports/mcp-cli"],
13
+ "env": {
14
+ "APPORTS_URL": "[https://appports.ports.gencat.cat/mcp](https://appports.ports.gencat.cat/mcp)",
15
+ "APPORTS_TOKEN": "tu_token_pat_aqui"
16
+ }
17
+ }
18
+ }
19
+ }
20
+ ```
package/bin/cli.js ADDED
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+
3
+ const axios = require("axios");
4
+ const readline = require("readline");
5
+
6
+ const API_URL = process.env.APPORTS_URL || "http://localhost:3000/mcp";
7
+ const AUTH_TOKEN = process.env.APPORTS_TOKEN || "";
8
+
9
+ if (!AUTH_TOKEN) {
10
+ console.error("[Apports MCP] Error: APPORTS_TOKEN no configurado.");
11
+ process.exit(1);
12
+ }
13
+
14
+ const rl = readline.createInterface({
15
+ input: process.stdin,
16
+ output: process.stdout,
17
+ terminal: false,
18
+ });
19
+
20
+ function emitJsonRpc(rawData) {
21
+ if (!rawData) return;
22
+
23
+ if (typeof rawData === "object") {
24
+ console.log(JSON.stringify(rawData));
25
+ return;
26
+ }
27
+
28
+ if (typeof rawData === "string") {
29
+ const lines = rawData.split("\n");
30
+ for (const line of lines) {
31
+ const trimmed = line.trim();
32
+ if (trimmed.startsWith("data:")) {
33
+ const jsonContent = trimmed.replace(/^data:\s*/, "").trim();
34
+ if (jsonContent) {
35
+ try {
36
+ console.log(JSON.stringify(JSON.parse(jsonContent)));
37
+ } catch (e) {
38
+ console.error("[Apports MCP] Error parseando SSE:", jsonContent);
39
+ }
40
+ }
41
+ } else if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
42
+ try {
43
+ console.log(JSON.stringify(JSON.parse(trimmed)));
44
+ } catch (e) {
45
+ // Ignorar no-JSON
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ rl.on("line", async (line) => {
53
+ if (!line.trim()) return;
54
+
55
+ let payload;
56
+ try {
57
+ payload = JSON.parse(line);
58
+ } catch {
59
+ return;
60
+ }
61
+
62
+ try {
63
+ const response = await axios.post(API_URL, payload, {
64
+ headers: {
65
+ Authorization: `Bearer ${AUTH_TOKEN}`,
66
+ "Content-Type": "application/json",
67
+ Accept: "application/json, text/event-stream",
68
+ },
69
+ responseType: "text",
70
+ });
71
+
72
+ emitJsonRpc(response.data);
73
+ } catch (error) {
74
+ const status = error.response?.status;
75
+ const responseData = error.response?.data;
76
+
77
+ console.error(
78
+ `[Apports MCP Error ${status || "HTTP"}]`,
79
+ responseData || error.message,
80
+ );
81
+
82
+ // 🔑 Si es una notificación (no tiene id), NO enviamos respuesta por STDOUT
83
+ if (payload?.id === undefined || payload?.id === null) {
84
+ return;
85
+ }
86
+
87
+ let errorMessage = error.message;
88
+ if (typeof responseData === "object" && responseData?.message) {
89
+ errorMessage = responseData.message;
90
+ } else if (typeof responseData === "string") {
91
+ errorMessage = responseData;
92
+ }
93
+
94
+ const jsonRpcError = {
95
+ jsonrpc: "2.0",
96
+ id: payload.id,
97
+ error: {
98
+ code: status === 401 ? -32001 : -32603,
99
+ message: `[HTTP ${status || "Error"}] ${errorMessage}`,
100
+ },
101
+ };
102
+
103
+ console.log(JSON.stringify(jsonRpcError));
104
+ }
105
+ });
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@apogea/apports-mcp",
3
+ "version": "1.0.0",
4
+ "description": "Puente CLI de STDIO a HTTP Streamable para el servidor MCP de Apports",
5
+ "main": "bin/cli.js",
6
+ "bin": {
7
+ "apports-mcp-cli": "./bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node bin/cli.js"
11
+ },
12
+ "dependencies": {
13
+ "axios": "^1.7.0"
14
+ },
15
+ "engines": {
16
+ "node": ">=18.0.0"
17
+ },
18
+ "keywords": [
19
+ "mcp",
20
+ "model-context-protocol",
21
+ "claude-desktop",
22
+ "apports",
23
+ "copilot"
24
+ ],
25
+ "author": "Apogea",
26
+ "license": "MIT"
27
+ }