mcp-fence 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 yjcho
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,309 @@
1
+ # mcp-fence
2
+
3
+ **The bidirectional firewall for MCP** -- scans inputs AND outputs, detects rug-pulls at runtime, zero config.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/mcp-fence)](https://www.npmjs.com/package/mcp-fence)
6
+ [![license](https://img.shields.io/npm/l/mcp-fence)](./LICENSE)
7
+ [![node](https://img.shields.io/node/v/mcp-fence)](https://nodejs.org/)
8
+ [![OWASP MCP](https://img.shields.io/badge/OWASP%20MCP%20Top%2010-7%2F10-blue)](#owasp-mcp-top-10-coverage)
9
+
10
+ ---
11
+
12
+ ## Why mcp-fence?
13
+
14
+ Most MCP security tools only inspect what goes **in** to a server. That misses half the attack surface.
15
+
16
+ - **Bidirectional scanning** -- Inspects both requests and responses. A compromised server can inject instructions in its output; mcp-fence catches that.
17
+ - **Rug-pull detection** -- Pins tool descriptions by hash at first approval. If a server silently changes what a tool does at runtime, mcp-fence flags it immediately.
18
+ - **Zero config** -- Works out of the box with secure defaults (monitor mode). No YAML required to get started.
19
+
20
+ ---
21
+
22
+ ## Quick Start
23
+
24
+ ```bash
25
+ # Install globally
26
+ npm install -g mcp-fence
27
+
28
+ # Proxy any MCP server
29
+ mcp-fence start -- npx @anthropic/mcp-server-filesystem /tmp
30
+ ```
31
+
32
+ Or run without installing:
33
+
34
+ ```bash
35
+ npx mcp-fence start -- npx @anthropic/mcp-server-filesystem /tmp
36
+ ```
37
+
38
+ That's it. mcp-fence sits between your MCP client and server, logging every suspicious finding to stderr and an SQLite audit trail.
39
+
40
+ ### Claude Desktop Integration
41
+
42
+ Add mcp-fence as a wrapper in your `claude_desktop_config.json`:
43
+
44
+ ```json
45
+ {
46
+ "mcpServers": {
47
+ "filesystem": {
48
+ "command": "npx",
49
+ "args": [
50
+ "mcp-fence",
51
+ "start",
52
+ "--mode", "enforce",
53
+ "--",
54
+ "npx", "@anthropic/mcp-server-filesystem", "/tmp"
55
+ ]
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ Your MCP server works exactly as before. mcp-fence just inspects traffic passing through.
62
+
63
+ ---
64
+
65
+ ## Features
66
+
67
+ | Feature | Description |
68
+ |---------|-------------|
69
+ | **Bidirectional scanning** | Scans both client requests and server responses for threats |
70
+ | **Prompt injection detection** | 20+ regex patterns covering instruction override, role hijacking, hidden instructions, multi-language attacks |
71
+ | **Secret leak detection** | 25+ patterns for AWS keys, GitHub tokens, private keys, connection strings, and more |
72
+ | **Rug-pull detection** | SHA-256 hash pinning of tool descriptions. Detects silent modification after initial approval |
73
+ | **Policy engine** | Tool-level allow/deny rules with glob patterns and argument validation |
74
+ | **Audit logging** | SQLite-backed event log with queryable CLI |
75
+ | **SARIF output** | Export findings in SARIF format for GitHub Security tab integration |
76
+ | **Zero-config defaults** | Monitor mode out of the box -- logs threats without blocking, so you never break a working setup |
77
+
78
+ ### Limitations (v0.1)
79
+
80
+ Detection is regex-based. It handles known patterns well but won't catch novel prompt injection via paraphrase or synonyms. ML-based semantic detection is planned for v0.4. Only stdio transport is supported; SSE and Streamable HTTP are coming in v0.3.
81
+
82
+ ---
83
+
84
+ ## OWASP MCP Top 10 Coverage
85
+
86
+ | ID | Risk | v0.1 | How |
87
+ |----|------|:----:|-----|
88
+ | MCP01 | Token/Secret Exposure | Yes | Secret pattern detection in requests and responses |
89
+ | MCP02 | Tool Poisoning | Yes | Tool description hash pinning (rug-pull detection) |
90
+ | MCP03 | Excessive Permissions | Yes | Policy engine with tool allow/deny + argument constraints |
91
+ | MCP04 | Command Injection | Yes | Command injection patterns in detection engine |
92
+ | MCP05 | Insecure Data Handling | -- | Planned for v0.2 |
93
+ | MCP06 | Insufficient Logging | Yes | SQLite audit log + SARIF export |
94
+ | MCP07 | Insufficient Auth | Yes | Policy enforcement + tool-level access control |
95
+ | MCP08 | Server Spoofing | -- | Planned for v0.2 |
96
+ | MCP09 | Supply Chain Compromise | -- | Planned for v0.2 |
97
+ | MCP10 | Context Injection | -- | Planned for v0.2 |
98
+
99
+ ---
100
+
101
+ ## Configuration
102
+
103
+ Generate a config file:
104
+
105
+ ```bash
106
+ mcp-fence init
107
+ ```
108
+
109
+ This creates `fence.config.yaml`:
110
+
111
+ ```yaml
112
+ # Operation mode: "monitor" (log only) or "enforce" (block threats)
113
+ mode: monitor
114
+
115
+ log:
116
+ level: info
117
+ # file: ./mcp-fence.log # uncomment to log to file
118
+
119
+ detection:
120
+ warnThreshold: 0.5 # score >= 0.5 triggers a warning
121
+ blockThreshold: 0.8 # score >= 0.8 triggers a block (enforce mode only)
122
+ maxInputSize: 10240 # bytes — inputs larger than this are truncated
123
+
124
+ policy:
125
+ defaultAction: allow
126
+ rules:
127
+ - tool: "exec_cmd"
128
+ action: deny
129
+ - tool: "read_file"
130
+ action: allow
131
+ args:
132
+ - name: path
133
+ denyPattern: "^\\.env$|^/etc/"
134
+ - tool: "write_*"
135
+ action: deny
136
+ ```
137
+
138
+ Config priority: **CLI flags > environment variables > YAML file > defaults**.
139
+
140
+ Environment variables: `MCP_FENCE_MODE` (`monitor` | `enforce`), `MCP_FENCE_LOG_LEVEL` (`debug` | `info` | `warn` | `error`).
141
+
142
+ ---
143
+
144
+ ## CLI Commands
145
+
146
+ ### `start` -- Run the security proxy
147
+
148
+ ```bash
149
+ # Basic usage
150
+ mcp-fence start -- npx @anthropic/mcp-server-filesystem /tmp
151
+
152
+ # With options
153
+ mcp-fence start --mode enforce --config ./fence.config.yaml -- node my-server.js
154
+ ```
155
+
156
+ ### `init` -- Generate default config
157
+
158
+ ```bash
159
+ mcp-fence init
160
+ mcp-fence init --output ./custom-config.yaml
161
+ ```
162
+
163
+ ### `scan` -- Standalone threat scan (no proxy needed)
164
+
165
+ ```bash
166
+ # Scan a file
167
+ mcp-fence scan ./suspicious-prompt.txt
168
+
169
+ # Scan inline text
170
+ mcp-fence scan --text "ignore all previous instructions"
171
+
172
+ # Scan server responses
173
+ mcp-fence scan ./response.json --direction response
174
+
175
+ # Output as JSON or SARIF
176
+ mcp-fence scan ./file.txt --format json
177
+ mcp-fence scan ./file.txt --format sarif > results.sarif
178
+ ```
179
+
180
+ ### `logs` -- Query the audit trail
181
+
182
+ ```bash
183
+ # Recent warnings
184
+ mcp-fence logs --since 1h --level warn
185
+
186
+ # Export to SARIF for GitHub
187
+ mcp-fence logs --format sarif > audit.sarif
188
+
189
+ # Filter by direction
190
+ mcp-fence logs --direction response --limit 50
191
+ ```
192
+
193
+ ### `status` -- Show config and capabilities
194
+
195
+ ```bash
196
+ mcp-fence status
197
+ mcp-fence status --config ./fence.config.yaml
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Architecture
203
+
204
+ ```
205
+ mcp-fence
206
+ ┌─────────────────────┐
207
+ [MCP Client] ──> │ 1. Detection Engine │ ──> [MCP Server]
208
+ stdin│ 2. Hash Pin Check │stdout
209
+ [MCP Client] <── │ 3. Policy Engine │ <── [MCP Server]
210
+ │ 4. Audit Logger │
211
+ └─────────────────────┘
212
+
213
+ [SQLite Audit DB]
214
+ ```
215
+
216
+ Every message flows through the same pipeline:
217
+
218
+ 1. **Intercept** -- Proxy captures the JSON-RPC message (request or response).
219
+ 2. **Detect** -- Detection engine runs injection, secret, and command-injection patterns against the message content.
220
+ 3. **Pin check** -- For `tools/list` responses, hash-pins tool descriptions and flags any changes.
221
+ 4. **Policy** -- Policy engine evaluates tool-level allow/deny rules and argument constraints.
222
+ 5. **Audit** -- Every scan result is logged to SQLite with timestamp, direction, decision, and findings.
223
+ 6. **Forward or block** -- In monitor mode, everything passes through (findings are logged). In enforce mode, messages exceeding the block threshold are rejected.
224
+
225
+ Modules are decoupled: detection doesn't import policy, audit doesn't import detection. The proxy orchestrates all communication between them through the `ScanResult` contract.
226
+
227
+ ---
228
+
229
+ ## Programmatic Usage
230
+
231
+ mcp-fence can be used as a library in your own Node.js applications:
232
+
233
+ ```typescript
234
+ import {
235
+ McpProxy,
236
+ DetectionEngine,
237
+ HashPinChecker,
238
+ MemoryHashStore,
239
+ PolicyEngine,
240
+ AuditLoggerImpl,
241
+ SqliteAuditStore,
242
+ loadConfig,
243
+ } from 'mcp-fence';
244
+
245
+ const config = loadConfig('./fence.config.yaml');
246
+
247
+ const proxy = new McpProxy({
248
+ serverCommand: 'npx',
249
+ serverArgs: ['@anthropic/mcp-server-filesystem', '/tmp'],
250
+ config,
251
+ scanner: new DetectionEngine(config.detection),
252
+ hashPinChecker: new HashPinChecker(new MemoryHashStore()),
253
+ policyEngine: new PolicyEngine(config.policy),
254
+ auditLogger: new AuditLoggerImpl(new SqliteAuditStore('./audit.db')),
255
+ });
256
+
257
+ await proxy.start();
258
+ ```
259
+
260
+ You can also use the detection engine standalone:
261
+
262
+ ```typescript
263
+ import { DetectionEngine, DEFAULT_CONFIG } from 'mcp-fence';
264
+
265
+ const engine = new DetectionEngine(DEFAULT_CONFIG.detection);
266
+
267
+ const result = await engine.scan(
268
+ { jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'read_file', arguments: { path: '/etc/passwd' } } },
269
+ 'request'
270
+ );
271
+
272
+ console.log(result.decision); // 'allow' | 'warn' | 'block'
273
+ console.log(result.findings); // Finding[]
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Roadmap
279
+
280
+ | Version | Focus |
281
+ |---------|-------|
282
+ | **v0.1** | stdio proxy, bidirectional scanning, secret detection, hash pinning, policy engine, SQLite audit, SARIF, CLI |
283
+ | **v0.2** | Audit log hardening (secret masking, HMAC integrity, DB size limits), shadow tool detection, Unicode normalization for arguments |
284
+ | **v0.3** | SSE + Streamable HTTP transport, JWT authentication, OPA policy server integration |
285
+ | **v0.4** | ML-based semantic detection (embedding similarity), session-level multi-step analysis |
286
+ | **v1.0** | Production-stable release |
287
+
288
+ ---
289
+
290
+ ## Contributing
291
+
292
+ Contributions are welcome. Please open an issue before submitting large changes so we can discuss the approach.
293
+
294
+ ```bash
295
+ git clone https://github.com/user/mcp-fence.git
296
+ cd mcp-fence
297
+ npm install
298
+ npm test # run tests
299
+ npm run typecheck # type checking
300
+ npm run lint # lint
301
+ ```
302
+
303
+ Security-critical modules (`src/detection/`, `src/integrity/`, `src/policy/local.ts`) require manual review on every PR. No exceptions.
304
+
305
+ ---
306
+
307
+ ## License
308
+
309
+ [MIT](./LICENSE)