@rsv_ink/ink-hub-mcp 0.1.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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -0
  3. package/dist/index.js +143 -0
  4. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 João Alves
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @rsv_ink/ink-hub-mcp
2
+
3
+ Cliente local que conecta Claude Desktop, Cursor e Zed ao servidor MCP do **Ink Hub**.
4
+
5
+ Clientes como o Claude Desktop só falam MCP via `stdio` — eles não conseguem se conectar diretamente a um servidor MCP remoto. Este pacote roda na sua máquina, recebe os comandos via `stdio` e repassa tudo para o servidor do Ink Hub de forma transparente.
6
+
7
+ ## Uso
8
+
9
+ Não precisa instalar nada. Adicione esse bloco no `claude_desktop_config.json` (ou config equivalente do Cursor / Zed):
10
+
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "ink-hub": {
15
+ "command": "npx",
16
+ "args": ["-y", "@rsv_ink/ink-hub-mcp"],
17
+ "env": {
18
+ "INK_HUB_URL": "https://seu-ink-hub.exemplo.com",
19
+ "MCP_AUTH_TOKEN": "seu-token"
20
+ }
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ Reinicie o cliente MCP — pronto.
27
+
28
+ ## Variáveis de ambiente
29
+
30
+ | Variável | Obrigatória | Descrição |
31
+ | ---------------- | ----------- | -------------------------------------------------------- |
32
+ | `INK_HUB_URL` | sim | URL base do servidor Ink Hub (sem barra final). |
33
+ | `MCP_AUTH_TOKEN` | sim | Token enviado em `Authorization: Bearer <token>`. |
34
+ | `DEBUG` | não | `true` para logar todas as mensagens MCP em `stderr`. |
35
+
36
+ ## Desenvolvimento
37
+
38
+ ```bash
39
+ git clone https://github.com/rsv-ink/ink-hub-mcp.git
40
+ cd ink-hub-mcp
41
+ npm install
42
+ npm test
43
+ npm run build
44
+ ```
45
+
46
+ Para subir o proxy localmente:
47
+
48
+ ```bash
49
+ INK_HUB_URL=https://... MCP_AUTH_TOKEN=... npm run dev
50
+ ```
51
+
52
+ ## Licença
53
+
54
+ MIT — veja [LICENSE](./LICENSE).
package/dist/index.js ADDED
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { JSONRPCRequestSchema } from "@modelcontextprotocol/sdk/types.js";
6
+
7
+ // src/transport.ts
8
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
9
+ var isDebug = process.env.DEBUG === "true";
10
+ var InkHubTransport = class {
11
+ constructor(baseUrl, authToken) {
12
+ this.baseUrl = baseUrl;
13
+ this.authToken = authToken;
14
+ const authHeaders = {
15
+ Authorization: `Bearer ${this.authToken}`
16
+ };
17
+ this.client = new StreamableHTTPClientTransport(this.baseUrl, {
18
+ requestInit: {
19
+ headers: authHeaders
20
+ }
21
+ });
22
+ this.client.onmessage = (message) => {
23
+ if (isDebug) console.error(`[DEBUG-MCP-RECV] <- ${JSON.stringify(message)}`);
24
+ this.onmessage?.(message);
25
+ };
26
+ this.client.onerror = (error) => {
27
+ console.error("[TRANSPORT-ERROR] HTTP Transport error:", error);
28
+ this.onerror?.(error);
29
+ };
30
+ this.client.onclose = () => {
31
+ if (isDebug) console.error("[DEBUG-MCP-CLOSE] Remote SSE connection closed");
32
+ this.onclose?.();
33
+ };
34
+ }
35
+ baseUrl;
36
+ authToken;
37
+ client;
38
+ onclose;
39
+ onerror;
40
+ onmessage;
41
+ async start() {
42
+ if (isDebug) console.error(`[DEBUG-MCP-START] Connecting to ${this.baseUrl.toString()}`);
43
+ await this.client.start();
44
+ }
45
+ async close() {
46
+ if (isDebug) console.error("[DEBUG-MCP-CLOSE] Closing remote connection");
47
+ await this.client.close();
48
+ }
49
+ async send(message) {
50
+ if (isDebug) console.error(`[DEBUG-MCP-SEND] -> ${JSON.stringify(message)}`);
51
+ await this.client.send(message);
52
+ }
53
+ };
54
+
55
+ // src/index.ts
56
+ import process2 from "process";
57
+ async function run() {
58
+ const serverUrlStr = process2.env.INK_HUB_URL;
59
+ const authToken = process2.env.MCP_AUTH_TOKEN;
60
+ if (!serverUrlStr) {
61
+ console.error("Error: INK_HUB_URL environment variable is not set.");
62
+ console.error("Set INK_HUB_URL in the MCP client config to point to your Ink Hub server.");
63
+ process2.exit(1);
64
+ }
65
+ if (!authToken) {
66
+ console.error("Error: MCP_AUTH_TOKEN environment variable is not set.");
67
+ process2.exit(1);
68
+ }
69
+ let serverUrl;
70
+ try {
71
+ serverUrl = new URL(`${serverUrlStr.replace(/\/$/, "")}/api/mcp`);
72
+ } catch (error) {
73
+ console.error(
74
+ `Error: Invalid INK_HUB_URL ("${serverUrlStr}"). Must be a valid URL.`
75
+ );
76
+ process2.exit(1);
77
+ }
78
+ const remoteTransport = new InkHubTransport(serverUrl, authToken);
79
+ remoteTransport.onerror = (error) => {
80
+ console.error(
81
+ "Warning: connection issue with the Ink Hub server:",
82
+ error.message
83
+ );
84
+ };
85
+ remoteTransport.onclose = () => {
86
+ console.error(
87
+ "Connection to the Ink Hub server was closed. The server may have timed out or restarted."
88
+ );
89
+ stdioTransport.onclose?.();
90
+ process2.exit(1);
91
+ };
92
+ const stdioTransport = new StdioServerTransport();
93
+ stdioTransport.onerror = (error) => {
94
+ console.error("stdio connection error:", error.message);
95
+ };
96
+ stdioTransport.onclose = () => {
97
+ console.error("stdio connection closed. Shutting down proxy.");
98
+ remoteTransport.close().catch(() => {
99
+ });
100
+ process2.exit(0);
101
+ };
102
+ remoteTransport.onmessage = async (message) => {
103
+ try {
104
+ await stdioTransport.send(message);
105
+ } catch (err) {
106
+ console.error("Error routing message from server to stdio:", err);
107
+ process2.exit(1);
108
+ }
109
+ };
110
+ stdioTransport.onmessage = async (message) => {
111
+ try {
112
+ await remoteTransport.send(message);
113
+ } catch (err) {
114
+ console.error("Error routing message from stdio to server:", err);
115
+ const parsedRequest = JSONRPCRequestSchema.safeParse(message);
116
+ if (parsedRequest.success) {
117
+ await stdioTransport.send({
118
+ jsonrpc: "2.0",
119
+ id: parsedRequest.data.id,
120
+ error: {
121
+ code: -32603,
122
+ message: `Proxy failed to route message: ${err instanceof Error ? err.message : String(err)}`
123
+ }
124
+ }).catch(() => {
125
+ });
126
+ }
127
+ }
128
+ };
129
+ try {
130
+ console.error("Connecting to Ink Hub MCP server...");
131
+ await remoteTransport.start();
132
+ console.error("Connected. Starting stdio transport...");
133
+ await stdioTransport.start();
134
+ } catch (error) {
135
+ const msg = error instanceof Error ? error.message : String(error);
136
+ console.error("Fatal error initializing transports:", msg);
137
+ process2.exit(1);
138
+ }
139
+ }
140
+ run().catch((err) => {
141
+ console.error("Unhandled error in proxy:", err);
142
+ process2.exit(1);
143
+ });
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@rsv_ink/ink-hub-mcp",
3
+ "version": "0.1.0",
4
+ "description": "Local MCP client that bridges stdio-based MCP clients (Claude Desktop, Cursor, Zed) to the remote Ink Hub MCP server.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "claude",
9
+ "anthropic",
10
+ "ink-hub",
11
+ "stdio",
12
+ "proxy"
13
+ ],
14
+ "license": "MIT",
15
+ "author": "João Alves <joao.alves@reserva.ink>",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/rsv-ink/ink-hub-mcp.git"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/rsv-ink/ink-hub-mcp/issues"
22
+ },
23
+ "homepage": "https://github.com/rsv-ink/ink-hub-mcp#readme",
24
+ "main": "dist/index.js",
25
+ "bin": {
26
+ "ink-hub-mcp": "dist/index.js"
27
+ },
28
+ "type": "module",
29
+ "files": [
30
+ "dist",
31
+ "README.md",
32
+ "LICENSE"
33
+ ],
34
+ "engines": {
35
+ "node": ">=18.0.0"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup src/index.ts --format esm --clean",
42
+ "dev": "tsx src/index.ts",
43
+ "test": "vitest run",
44
+ "prepublishOnly": "npm run test && npm run build"
45
+ },
46
+ "dependencies": {
47
+ "@modelcontextprotocol/sdk": "^1.29.0",
48
+ "eventsource": "^4.1.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^25.6.2",
52
+ "tsup": "^8.5.1",
53
+ "tsx": "^4.21.0",
54
+ "typescript": "^6.0.3",
55
+ "vitest": "^4.1.5"
56
+ }
57
+ }