@mcp-html-bridge/proxy 0.5.1 → 0.5.2

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,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ // ── Proxy adapter entry point ──
5
+ const proxy_server_js_1 = require("./proxy-server.js");
6
+ const targetCommand = process.argv[2];
7
+ if (!targetCommand) {
8
+ console.error('Usage: mcp-proxy <target-server-command> [args...]');
9
+ console.error('Example: mcp-proxy "npx -y @modelcontextprotocol/server-filesystem /tmp"');
10
+ process.exit(1);
11
+ }
12
+ const targetArgs = process.argv.slice(3);
13
+ const proxy = new proxy_server_js_1.MCPProxyServer(targetCommand, targetArgs);
14
+ proxy.start();
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,kCAAkC;AAClC,uDAAmD;AAEnD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtC,IAAI,CAAC,aAAa,EAAE,CAAC;IACnB,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACpE,OAAO,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC1F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACzC,MAAM,KAAK,GAAG,IAAI,gCAAc,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;AAC5D,KAAK,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * MCP Proxy that sits between a client and a target MCP server.
3
+ * It forwards all traffic transparently, but enhances tool call results
4
+ * with rendered HTML blocks.
5
+ */
6
+ export declare class MCPProxyServer {
7
+ private targetCommand;
8
+ private targetArgs;
9
+ private targetProcess;
10
+ private clientBuffer;
11
+ private serverBuffer;
12
+ constructor(targetCommand: string, targetArgs?: string[]);
13
+ /**
14
+ * Start the proxy. Reads from stdin, writes to stdout.
15
+ * Spawns the target MCP server as a subprocess.
16
+ */
17
+ start(): void;
18
+ private processServerBuffer;
19
+ private enhanceResponse;
20
+ }
21
+ //# sourceMappingURL=proxy-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-server.d.ts","sourceRoot":"","sources":["../src/proxy-server.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,qBAAa,cAAc;IAMvB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,UAAU;IANpB,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,YAAY,CAAM;gBAGhB,aAAa,EAAE,MAAM,EACrB,UAAU,GAAE,MAAM,EAAO;IAGnC;;;OAGG;IACH,KAAK,IAAI,IAAI;IAmCb,OAAO,CAAC,mBAAmB;IA4B3B,OAAO,CAAC,eAAe;CAwCxB"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MCPProxyServer = void 0;
4
+ // ── MCP Proxy Server: intercepts tool results and enhances with HTML ──
5
+ const node_child_process_1 = require("node:child_process");
6
+ const ui_engine_1 = require("@mcp-html-bridge/ui-engine");
7
+ /**
8
+ * MCP Proxy that sits between a client and a target MCP server.
9
+ * It forwards all traffic transparently, but enhances tool call results
10
+ * with rendered HTML blocks.
11
+ */
12
+ class MCPProxyServer {
13
+ targetCommand;
14
+ targetArgs;
15
+ targetProcess = null;
16
+ clientBuffer = '';
17
+ serverBuffer = '';
18
+ constructor(targetCommand, targetArgs = []) {
19
+ this.targetCommand = targetCommand;
20
+ this.targetArgs = targetArgs;
21
+ }
22
+ /**
23
+ * Start the proxy. Reads from stdin, writes to stdout.
24
+ * Spawns the target MCP server as a subprocess.
25
+ */
26
+ start() {
27
+ // Spawn target MCP server
28
+ const [cmd, ...defaultArgs] = this.targetCommand.split(/\s+/);
29
+ this.targetProcess = (0, node_child_process_1.spawn)(cmd, [...defaultArgs, ...this.targetArgs], {
30
+ stdio: ['pipe', 'pipe', 'pipe'],
31
+ });
32
+ // Forward stderr from target
33
+ this.targetProcess.stderr?.on('data', (chunk) => {
34
+ process.stderr.write(chunk);
35
+ });
36
+ // Client → Target (forward requests transparently)
37
+ process.stdin.on('data', (chunk) => {
38
+ this.targetProcess?.stdin?.write(chunk);
39
+ });
40
+ // Target → Client (intercept and enhance responses)
41
+ this.targetProcess.stdout?.on('data', (chunk) => {
42
+ this.serverBuffer += chunk.toString();
43
+ this.processServerBuffer();
44
+ });
45
+ this.targetProcess.on('exit', (code) => {
46
+ process.stderr.write(`[proxy] Target server exited with code ${code}\n`);
47
+ process.exit(code ?? 1);
48
+ });
49
+ process.stdin.on('end', () => {
50
+ this.targetProcess?.stdin?.end();
51
+ });
52
+ process.stderr.write('[proxy] MCP Proxy started\n');
53
+ }
54
+ processServerBuffer() {
55
+ while (true) {
56
+ const headerEnd = this.serverBuffer.indexOf('\r\n\r\n');
57
+ if (headerEnd === -1)
58
+ break;
59
+ const header = this.serverBuffer.slice(0, headerEnd);
60
+ const match = header.match(/Content-Length:\s*(\d+)/i);
61
+ if (!match) {
62
+ // Forward non-JSON-RPC content as-is
63
+ const chunk = this.serverBuffer.slice(0, headerEnd + 4);
64
+ process.stdout.write(chunk);
65
+ this.serverBuffer = this.serverBuffer.slice(headerEnd + 4);
66
+ continue;
67
+ }
68
+ const contentLength = parseInt(match[1], 10);
69
+ const bodyStart = headerEnd + 4;
70
+ if (this.serverBuffer.length < bodyStart + contentLength)
71
+ break;
72
+ const body = this.serverBuffer.slice(bodyStart, bodyStart + contentLength);
73
+ this.serverBuffer = this.serverBuffer.slice(bodyStart + contentLength);
74
+ const enhanced = this.enhanceResponse(body);
75
+ const newHeader = `Content-Length: ${Buffer.byteLength(enhanced)}\r\n\r\n`;
76
+ process.stdout.write(newHeader + enhanced);
77
+ }
78
+ }
79
+ enhanceResponse(body) {
80
+ try {
81
+ const msg = JSON.parse(body);
82
+ // Only enhance tool call results
83
+ if (msg.id === undefined || !msg.result?.content)
84
+ return body;
85
+ // Check if this looks like a tools/call response
86
+ const textContent = msg.result.content.find((c) => c.type === 'text' && c.text);
87
+ if (!textContent?.text)
88
+ return body;
89
+ // Try to parse the text content as JSON for rendering
90
+ let data;
91
+ try {
92
+ data = JSON.parse(textContent.text);
93
+ }
94
+ catch {
95
+ // Not JSON — try rendering as reading block
96
+ data = textContent.text;
97
+ }
98
+ // Generate HTML
99
+ const html = (0, ui_engine_1.renderFromDataSync)(data, { title: 'MCP Result' });
100
+ // Append HTML block to the response content
101
+ msg.result.content.push({
102
+ type: 'text',
103
+ text: `\n\`\`\`mcp-html\n${html}\n\`\`\``,
104
+ });
105
+ return JSON.stringify(msg);
106
+ }
107
+ catch {
108
+ return body;
109
+ }
110
+ }
111
+ }
112
+ exports.MCPProxyServer = MCPProxyServer;
113
+ //# sourceMappingURL=proxy-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-server.js","sourceRoot":"","sources":["../src/proxy-server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@mcp-html-bridge/proxy",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "MCP proxy that intercepts & enhances responses with HTML UI",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
+ "files": [
8
+ "dist/"
9
+ ],
7
10
  "scripts": {
8
11
  "build": "tsc -p tsconfig.json",
9
12
  "clean": "rm -rf dist"
package/src/index.ts DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env node
2
- // ── Proxy adapter entry point ──
3
- import { MCPProxyServer } from './proxy-server.js';
4
-
5
- const targetCommand = process.argv[2];
6
- if (!targetCommand) {
7
- console.error('Usage: mcp-proxy <target-server-command> [args...]');
8
- console.error('Example: mcp-proxy "npx -y @modelcontextprotocol/server-filesystem /tmp"');
9
- process.exit(1);
10
- }
11
-
12
- const targetArgs = process.argv.slice(3);
13
- const proxy = new MCPProxyServer(targetCommand, targetArgs);
14
- proxy.start();
@@ -1,127 +0,0 @@
1
- // ── MCP Proxy Server: intercepts tool results and enhances with HTML ──
2
- import { spawn, type ChildProcess } from 'node:child_process';
3
- import { renderFromDataSync } from '@mcp-html-bridge/ui-engine';
4
-
5
- /**
6
- * MCP Proxy that sits between a client and a target MCP server.
7
- * It forwards all traffic transparently, but enhances tool call results
8
- * with rendered HTML blocks.
9
- */
10
- export class MCPProxyServer {
11
- private targetProcess: ChildProcess | null = null;
12
- private clientBuffer = '';
13
- private serverBuffer = '';
14
-
15
- constructor(
16
- private targetCommand: string,
17
- private targetArgs: string[] = []
18
- ) {}
19
-
20
- /**
21
- * Start the proxy. Reads from stdin, writes to stdout.
22
- * Spawns the target MCP server as a subprocess.
23
- */
24
- start(): void {
25
- // Spawn target MCP server
26
- const [cmd, ...defaultArgs] = this.targetCommand.split(/\s+/);
27
- this.targetProcess = spawn(cmd, [...defaultArgs, ...this.targetArgs], {
28
- stdio: ['pipe', 'pipe', 'pipe'],
29
- });
30
-
31
- // Forward stderr from target
32
- this.targetProcess.stderr?.on('data', (chunk: Buffer) => {
33
- process.stderr.write(chunk);
34
- });
35
-
36
- // Client → Target (forward requests transparently)
37
- process.stdin.on('data', (chunk: Buffer) => {
38
- this.targetProcess?.stdin?.write(chunk);
39
- });
40
-
41
- // Target → Client (intercept and enhance responses)
42
- this.targetProcess.stdout?.on('data', (chunk: Buffer) => {
43
- this.serverBuffer += chunk.toString();
44
- this.processServerBuffer();
45
- });
46
-
47
- this.targetProcess.on('exit', (code) => {
48
- process.stderr.write(`[proxy] Target server exited with code ${code}\n`);
49
- process.exit(code ?? 1);
50
- });
51
-
52
- process.stdin.on('end', () => {
53
- this.targetProcess?.stdin?.end();
54
- });
55
-
56
- process.stderr.write('[proxy] MCP Proxy started\n');
57
- }
58
-
59
- private processServerBuffer(): void {
60
- while (true) {
61
- const headerEnd = this.serverBuffer.indexOf('\r\n\r\n');
62
- if (headerEnd === -1) break;
63
-
64
- const header = this.serverBuffer.slice(0, headerEnd);
65
- const match = header.match(/Content-Length:\s*(\d+)/i);
66
- if (!match) {
67
- // Forward non-JSON-RPC content as-is
68
- const chunk = this.serverBuffer.slice(0, headerEnd + 4);
69
- process.stdout.write(chunk);
70
- this.serverBuffer = this.serverBuffer.slice(headerEnd + 4);
71
- continue;
72
- }
73
-
74
- const contentLength = parseInt(match[1], 10);
75
- const bodyStart = headerEnd + 4;
76
- if (this.serverBuffer.length < bodyStart + contentLength) break;
77
-
78
- const body = this.serverBuffer.slice(bodyStart, bodyStart + contentLength);
79
- this.serverBuffer = this.serverBuffer.slice(bodyStart + contentLength);
80
-
81
- const enhanced = this.enhanceResponse(body);
82
- const newHeader = `Content-Length: ${Buffer.byteLength(enhanced)}\r\n\r\n`;
83
- process.stdout.write(newHeader + enhanced);
84
- }
85
- }
86
-
87
- private enhanceResponse(body: string): string {
88
- try {
89
- const msg = JSON.parse(body) as {
90
- id?: number;
91
- result?: { content?: Array<{ type: string; text?: string }> };
92
- method?: string;
93
- };
94
-
95
- // Only enhance tool call results
96
- if (msg.id === undefined || !msg.result?.content) return body;
97
-
98
- // Check if this looks like a tools/call response
99
- const textContent = msg.result.content.find(
100
- (c) => c.type === 'text' && c.text
101
- );
102
- if (!textContent?.text) return body;
103
-
104
- // Try to parse the text content as JSON for rendering
105
- let data: unknown;
106
- try {
107
- data = JSON.parse(textContent.text);
108
- } catch {
109
- // Not JSON — try rendering as reading block
110
- data = textContent.text;
111
- }
112
-
113
- // Generate HTML
114
- const html = renderFromDataSync(data, { title: 'MCP Result' });
115
-
116
- // Append HTML block to the response content
117
- msg.result.content.push({
118
- type: 'text',
119
- text: `\n\`\`\`mcp-html\n${html}\n\`\`\``,
120
- });
121
-
122
- return JSON.stringify(msg);
123
- } catch {
124
- return body;
125
- }
126
- }
127
- }
package/tsconfig.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "./dist",
5
- "rootDir": "./src"
6
- },
7
- "include": ["src/**/*"],
8
- "references": [
9
- { "path": "../core-ui-engine" }
10
- ]
11
- }