@flarewatch/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 (3) hide show
  1. package/README.md +87 -0
  2. package/dist/bridge.js +145 -0
  3. package/package.json +41 -0
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # @flarewatch/mcp
2
+
3
+ stdio→HTTPS bridge for the FlareWatch MCP server.
4
+
5
+ Lets stdio-only MCP clients (Claude Desktop, Cursor, Continue) reach
6
+ the remote endpoint at `https://mcp.flarewatch.io/api/mcp` without
7
+ each client having to implement the Streamable HTTP transport.
8
+
9
+ ## Install / use
10
+
11
+ No install needed — `npx` will fetch on demand:
12
+
13
+ ```bash
14
+ npx -y @flarewatch/mcp
15
+ ```
16
+
17
+ ### Claude Desktop
18
+
19
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "flarewatch": {
25
+ "command": "npx",
26
+ "args": ["-y", "@flarewatch/mcp"]
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ Restart Claude Desktop. The 13 FlareWatch tools (validators, FTSO
33
+ providers, scoring methodology, agent transparency, etc.) become
34
+ available in every conversation.
35
+
36
+ ### Cursor
37
+
38
+ Cursor supports Streamable HTTP natively — you don't need this bridge.
39
+ Configure directly:
40
+
41
+ ```json
42
+ {
43
+ "url": "https://mcp.flarewatch.io/api/mcp"
44
+ }
45
+ ```
46
+
47
+ ### Continue.dev
48
+
49
+ ```json
50
+ {
51
+ "experimental": {
52
+ "modelContextProtocolServers": [
53
+ {
54
+ "transport": { "type": "stdio", "command": "npx", "args": ["-y", "@flarewatch/mcp"] }
55
+ }
56
+ ]
57
+ }
58
+ }
59
+ ```
60
+
61
+ ## Environment overrides
62
+
63
+ | Variable | Default | Purpose |
64
+ |---|---|---|
65
+ | `FLAREWATCH_MCP_URL` | `https://mcp.flarewatch.io/api/mcp` | Endpoint to forward to. Useful for preview deploys or local dev. |
66
+ | `FLAREWATCH_MCP_TIMEOUT_MS` | `30000` | Per-request HTTP timeout in ms. |
67
+
68
+ ## What this bridge does NOT do
69
+
70
+ It's intentionally dumb. ~150 LoC. The server is the single source of
71
+ truth for:
72
+
73
+ - Tool definitions
74
+ - Resource content
75
+ - Rate limiting
76
+ - Quarantine / honeypot / classifier walls
77
+ - Response signing
78
+
79
+ The bridge just forwards JSON-RPC frames between stdio and HTTPS. No
80
+ caching, no retries, no fallback. If the remote endpoint is down, the
81
+ bridge surfaces the upstream error rather than attempting recovery.
82
+
83
+ ## Verification
84
+
85
+ Every tool response carries a `verification_signature` HMAC. To verify
86
+ a citation came from this server, call the `verify_response` tool with
87
+ the cited payload + signature.
package/dist/bridge.js ADDED
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @flarewatch/mcp — stdio↔HTTPS bridge for the FlareWatch MCP server.
4
+ *
5
+ * Speaks MCP-over-stdio on its standard input/output and forwards
6
+ * every JSON-RPC request to the remote endpoint at
7
+ * https://mcp.flarewatch.io/api/mcp. Lets stdio-only MCP clients
8
+ * (Claude Desktop, Cursor's filesystem-MCP integration, Continue's
9
+ * stdio transport, etc.) reach the remote server without each client
10
+ * having to implement Streamable HTTP.
11
+ *
12
+ * ~150 LoC of dumb forwarding. NOT a re-implementation of tools or
13
+ * resources — the server is the single source of truth.
14
+ *
15
+ * Environment overrides:
16
+ * FLAREWATCH_MCP_URL — point at a non-default endpoint (preview /
17
+ * local dev). Defaults to https://mcp.flarewatch.io/api/mcp.
18
+ * FLAREWATCH_MCP_TIMEOUT_MS — per-request HTTP timeout (default 30000).
19
+ *
20
+ * Usage:
21
+ * npx @flarewatch/mcp
22
+ *
23
+ * Claude Desktop config:
24
+ * {
25
+ * "mcpServers": {
26
+ * "flarewatch": {
27
+ * "command": "npx",
28
+ * "args": ["-y", "@flarewatch/mcp"]
29
+ * }
30
+ * }
31
+ * }
32
+ */
33
+ import { createInterface } from "node:readline";
34
+ import { stdin, stdout, stderr } from "node:process";
35
+ const DEFAULT_URL = "https://mcp.flarewatch.io/api/mcp";
36
+ const URL = process.env.FLAREWATCH_MCP_URL ?? DEFAULT_URL;
37
+ const TIMEOUT_MS = Number(process.env.FLAREWATCH_MCP_TIMEOUT_MS ?? "30000");
38
+ const VERSION = "0.1.0";
39
+ function write(obj) {
40
+ stdout.write(JSON.stringify(obj) + "\n");
41
+ }
42
+ function logStderr(msg, extra) {
43
+ // Stderr only — the MCP client reads JSON from stdout, so any
44
+ // diagnostic we emit must go to stderr to avoid corrupting the
45
+ // wire protocol.
46
+ const line = extra
47
+ ? `[flarewatch-mcp] ${msg} ${JSON.stringify(extra)}`
48
+ : `[flarewatch-mcp] ${msg}`;
49
+ stderr.write(line + "\n");
50
+ }
51
+ async function forward(req) {
52
+ const controller = new AbortController();
53
+ const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
54
+ try {
55
+ const res = await fetch(URL, {
56
+ method: "POST",
57
+ headers: {
58
+ "Content-Type": "application/json",
59
+ "User-Agent": `flarewatch-mcp-bridge/${VERSION}`,
60
+ "MCP-Protocol-Version": "2025-06-18",
61
+ },
62
+ body: JSON.stringify(req),
63
+ signal: controller.signal,
64
+ });
65
+ if (res.status === 204) {
66
+ // Notification reply — no body.
67
+ return null;
68
+ }
69
+ if (!res.ok) {
70
+ return {
71
+ jsonrpc: "2.0",
72
+ id: req.id ?? null,
73
+ error: {
74
+ code: -32603,
75
+ message: `bridge: upstream HTTP ${res.status}`,
76
+ },
77
+ };
78
+ }
79
+ const parsed = (await res.json());
80
+ if (Array.isArray(parsed)) {
81
+ // Batch — return only the first response that matches the id.
82
+ // stdio doesn't support batches well; the bridge accepts only
83
+ // single requests at a time, so this branch shouldn't fire in
84
+ // practice. Defensive return so we don't crash.
85
+ const match = parsed.find((r) => r.id === req.id);
86
+ return match ?? null;
87
+ }
88
+ return parsed;
89
+ }
90
+ catch (e) {
91
+ return {
92
+ jsonrpc: "2.0",
93
+ id: req.id ?? null,
94
+ error: {
95
+ code: -32603,
96
+ message: `bridge: forward failed — ${e instanceof Error ? e.message : String(e)}`,
97
+ },
98
+ };
99
+ }
100
+ finally {
101
+ clearTimeout(timer);
102
+ }
103
+ }
104
+ async function main() {
105
+ logStderr(`starting; forwarding to ${URL}`);
106
+ const rl = createInterface({
107
+ input: stdin,
108
+ crlfDelay: Infinity,
109
+ });
110
+ for await (const line of rl) {
111
+ if (!line.trim())
112
+ continue;
113
+ let req;
114
+ try {
115
+ req = JSON.parse(line);
116
+ }
117
+ catch (e) {
118
+ write({
119
+ jsonrpc: "2.0",
120
+ id: null,
121
+ error: {
122
+ code: -32700,
123
+ message: `bridge: parse error — ${e instanceof Error ? e.message : String(e)}`,
124
+ },
125
+ });
126
+ continue;
127
+ }
128
+ const isNotification = req.id === undefined || req.id === null;
129
+ const response = await forward(req);
130
+ if (response === null) {
131
+ // Notification or 204 — no stdio output.
132
+ if (!isNotification) {
133
+ // Server returned 204 to a request that had an id — synthesize
134
+ // an empty success so the client doesn't hang forever.
135
+ write({ jsonrpc: "2.0", id: req.id ?? null, result: {} });
136
+ }
137
+ continue;
138
+ }
139
+ write(response);
140
+ }
141
+ }
142
+ main().catch((e) => {
143
+ logStderr("fatal", { error: e instanceof Error ? e.message : String(e) });
144
+ process.exit(1);
145
+ });
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@flarewatch/mcp",
3
+ "version": "0.1.0",
4
+ "description": "stdio→HTTPS bridge for the FlareWatch MCP server. Lets stdio-only MCP clients (Claude Desktop, Cursor, etc.) attach via `npx @flarewatch/mcp`.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "flarewatch-mcp": "dist/bridge.js"
9
+ },
10
+ "main": "dist/bridge.js",
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "start": "node dist/bridge.js",
18
+ "dev": "tsc --watch",
19
+ "prepublishOnly": "tsc"
20
+ },
21
+ "engines": {
22
+ "node": ">=18"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^20",
26
+ "typescript": "^5"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/nbridges333/flarewatch.git",
31
+ "directory": "packages/mcp-bridge"
32
+ },
33
+ "keywords": [
34
+ "mcp",
35
+ "model-context-protocol",
36
+ "flare",
37
+ "flarewatch",
38
+ "ftso",
39
+ "validator"
40
+ ]
41
+ }