@kevinbermudezc/context-guard 1.1.1 → 1.2.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/README.md +67 -1
- package/dist/bin/mcp-server.d.ts +3 -0
- package/dist/bin/mcp-server.d.ts.map +1 -0
- package/dist/bin/mcp-server.js +328 -0
- package/dist/bin/mcp-server.js.map +1 -0
- package/dist/tests/mcp-server.test.d.ts +2 -0
- package/dist/tests/mcp-server.test.d.ts.map +1 -0
- package/dist/tests/mcp-server.test.js +215 -0
- package/dist/tests/mcp-server.test.js.map +1 -0
- package/examples/claude-settings.json +15 -0
- package/examples/mcp-configs/antigravity-mcp.json +12 -0
- package/examples/mcp-configs/claude-desktop.json +12 -0
- package/examples/mcp-configs/cursor-mcp.json +12 -0
- package/package.json +15 -5
package/README.md
CHANGED
|
@@ -145,7 +145,73 @@ That's it! When Claude Code attempts to run `Read` (or raw bash reads like `cat
|
|
|
145
145
|
|
|
146
146
|
---
|
|
147
147
|
|
|
148
|
-
##
|
|
148
|
+
## 🔌 MCP Server — Universal Agent Integration (Phase 2)
|
|
149
|
+
|
|
150
|
+
ContextGuard ships a built-in **Model Context Protocol (MCP) server** compatible with any MCP host: **Cursor, Windsurf, Claude Desktop, Antigravity (AGY), Zed**, and more.
|
|
151
|
+
|
|
152
|
+
The MCP server exposes three tools:
|
|
153
|
+
|
|
154
|
+
| Tool | Description | Cost | Latency |
|
|
155
|
+
|---|---|---|---|
|
|
156
|
+
| `read_file_safe` | Protected file read — passthrough for small files, AST skeleton for large ones, block for binaries/lockfiles | **\$0.00** | **< 5ms** |
|
|
157
|
+
| `inspect_outline` | Instant structural outline (classes, functions, types, signals) with line numbers | **\$0.00** | **< 5ms** |
|
|
158
|
+
| `grep_distilled` | Pattern search returning only structural context around matches, never full file dumps | **\$0.00** | **< 50ms** |
|
|
159
|
+
|
|
160
|
+
### Install & Run
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# One-shot (no install):
|
|
164
|
+
npx -y @kevinbermudezc/context-guard context-guard-mcp
|
|
165
|
+
|
|
166
|
+
# Or as a local dependency:
|
|
167
|
+
pnpm add -D @kevinbermudezc/context-guard
|
|
168
|
+
node ./node_modules/@kevinbermudezc/context-guard/dist/bin/mcp-server.js
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### 🖱️ Cursor (`~/.cursor/mcp.json`)
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"mcpServers": {
|
|
176
|
+
"context-guard": {
|
|
177
|
+
"command": "npx",
|
|
178
|
+
"args": ["-y", "@kevinbermudezc/context-guard@latest", "context-guard-mcp"]
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 🤖 Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_config.json`)
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"mcpServers": {
|
|
189
|
+
"context-guard": {
|
|
190
|
+
"command": "npx",
|
|
191
|
+
"args": ["-y", "@kevinbermudezc/context-guard@latest", "context-guard-mcp"]
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 🪁 Antigravity / Google AGY (`.agents/mcp.json` or `~/.config/agy/mcp.json`)
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"mcpServers": {
|
|
202
|
+
"context-guard": {
|
|
203
|
+
"command": "npx",
|
|
204
|
+
"args": ["-y", "@kevinbermudezc/context-guard@latest", "context-guard-mcp"]
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
> **Note:** Configuration examples are also available in [`examples/mcp-configs/`](./examples/mcp-configs/).
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## 🛠️ CLI Usage (Claude Code Hook)
|
|
149
215
|
|
|
150
216
|
You can also use ContextGuard directly as a command-line tool:
|
|
151
217
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../bin/mcp-server.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ContextGuard MCP Server (Phase 2)
|
|
4
|
+
* Universal Model Context Protocol server exposing ContextGuard's context
|
|
5
|
+
* admission and token optimization engine as MCP tools.
|
|
6
|
+
*
|
|
7
|
+
* Compatible with: Claude Desktop, Cursor, Windsurf, Antigravity (AGY), Zed.
|
|
8
|
+
* Transport: stdio (JSON-RPC 2.0)
|
|
9
|
+
* SDK: @modelcontextprotocol/server v2 (2026-07-28 spec)
|
|
10
|
+
*
|
|
11
|
+
* Tools:
|
|
12
|
+
* read_file_safe — Protected file read with size guard + AST skeleton fallback
|
|
13
|
+
* inspect_outline — Instant structural outline of any source file (<5ms, $0.00)
|
|
14
|
+
* grep_distilled — Pattern search returning structural context around matches
|
|
15
|
+
*/
|
|
16
|
+
import { McpServer } from '@modelcontextprotocol/server';
|
|
17
|
+
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';
|
|
18
|
+
import { z } from 'zod';
|
|
19
|
+
import fs from 'node:fs';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
import { execSync } from 'node:child_process';
|
|
22
|
+
import { processWithContextGuard } from '../src/index.js';
|
|
23
|
+
import { extractCodeSkeleton, isSupportedExtension } from '../src/skeletonizer.js';
|
|
24
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
25
|
+
const SERVER_NAME = 'context-guard';
|
|
26
|
+
const SERVER_VERSION = '1.2.0';
|
|
27
|
+
// Native Claude Code / multimodal formats — allow full passthrough
|
|
28
|
+
const NATIVE_MEDIA_EXTS = new Set([
|
|
29
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.ico', '.bmp', '.avif',
|
|
30
|
+
'.pdf', '.ipynb'
|
|
31
|
+
]);
|
|
32
|
+
// ─── Server Setup ─────────────────────────────────────────────────────────────
|
|
33
|
+
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION });
|
|
34
|
+
// ─── Tool: read_file_safe ─────────────────────────────────────────────────────
|
|
35
|
+
server.registerTool('read_file_safe', {
|
|
36
|
+
title: 'Read File (ContextGuard Protected)',
|
|
37
|
+
description: [
|
|
38
|
+
'Reads a source file through the ContextGuard admission layer.',
|
|
39
|
+
'• If the file is small (≤300 lines / ≤25 KB): returns full content directly.',
|
|
40
|
+
'• If the file is large: returns an AST structural skeleton with line-tagged signatures.',
|
|
41
|
+
'• If the file is a binary (wasm/zip/sqlite/dll), lockfile, or minified bundle: returns an informative block message with CLI alternatives.',
|
|
42
|
+
'• If start_line / end_line are provided: returns the exact slice without applying the guard.',
|
|
43
|
+
'This tool replaces raw "Read file" calls and prevents context window flooding from large files.'
|
|
44
|
+
].join('\n'),
|
|
45
|
+
inputSchema: {
|
|
46
|
+
file_path: z.string().describe('Absolute or relative path to the file to read.'),
|
|
47
|
+
start_line: z.number().int().positive().optional().describe('First line to read (1-indexed). Bypasses size guard if set.'),
|
|
48
|
+
end_line: z.number().int().positive().optional().describe('Last line to read (1-indexed, inclusive). Bypasses size guard if set.'),
|
|
49
|
+
query: z.string().optional().describe('Optional semantic question. If provided, the file is passed to a worker model (Gemini Flash / Ollama) for summarization instead of AST extraction.')
|
|
50
|
+
}
|
|
51
|
+
}, async ({ file_path, start_line, end_line, query }) => {
|
|
52
|
+
try {
|
|
53
|
+
const resolved = path.resolve(process.cwd(), file_path);
|
|
54
|
+
// File existence check
|
|
55
|
+
if (!fs.existsSync(resolved)) {
|
|
56
|
+
return {
|
|
57
|
+
content: [{
|
|
58
|
+
type: 'text',
|
|
59
|
+
text: `⚠️ [CONTEXTGUARD] File not found: ${file_path}`
|
|
60
|
+
}]
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (fs.statSync(resolved).isDirectory()) {
|
|
64
|
+
return {
|
|
65
|
+
content: [{
|
|
66
|
+
type: 'text',
|
|
67
|
+
text: `⚠️ [CONTEXTGUARD] Path is a directory: ${file_path}. Use a file path.`
|
|
68
|
+
}]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const ext = path.extname(resolved).toLowerCase();
|
|
72
|
+
// Native multimodal / notebook formats — passthrough directly
|
|
73
|
+
if (NATIVE_MEDIA_EXTS.has(ext)) {
|
|
74
|
+
const raw = fs.readFileSync(resolved);
|
|
75
|
+
const isText = ext === '.ipynb' || ext === '.svg';
|
|
76
|
+
return {
|
|
77
|
+
content: [{
|
|
78
|
+
type: 'text',
|
|
79
|
+
text: isText
|
|
80
|
+
? raw.toString('utf-8')
|
|
81
|
+
: `[Native binary format: ${ext}. Use multimodal vision tool or platform viewer to inspect.]`
|
|
82
|
+
}]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Run through ContextGuard engine
|
|
86
|
+
const result = await processWithContextGuard({
|
|
87
|
+
filePath: file_path,
|
|
88
|
+
startLine: start_line,
|
|
89
|
+
endLine: end_line,
|
|
90
|
+
query: query ?? ''
|
|
91
|
+
});
|
|
92
|
+
// Format the response with status metadata header
|
|
93
|
+
const statusBadge = {
|
|
94
|
+
PASSTHROUGH_FULL: '✅ PASSTHROUGH',
|
|
95
|
+
PASSTHROUGH_SLICE: '✅ SLICE',
|
|
96
|
+
SHUNTED_LOCAL_AST: '🛡️ AST SKELETON',
|
|
97
|
+
SHUNTED_WORKER_MODEL: '🤖 WORKER SUMMARY',
|
|
98
|
+
SHUNT_FALLBACK: '⚠️ FALLBACK',
|
|
99
|
+
BLOCKED_BINARY: '🛑 BLOCKED (BINARY)',
|
|
100
|
+
BLOCKED_LOCKFILE: '🛑 BLOCKED (LOCKFILE)',
|
|
101
|
+
BLOCKED_MINIFIED: '🛑 BLOCKED (MINIFIED)',
|
|
102
|
+
ERROR: '❌ ERROR'
|
|
103
|
+
};
|
|
104
|
+
const badge = statusBadge[result.status] ?? result.status;
|
|
105
|
+
const meta = result.totalLines
|
|
106
|
+
? `${result.totalLines} lines · ${((result.sizeBytes ?? 0) / 1024).toFixed(1)} KB`
|
|
107
|
+
: '';
|
|
108
|
+
const header = meta
|
|
109
|
+
? `<!-- [CONTEXTGUARD ${badge}] ${meta} -->\n`
|
|
110
|
+
: `<!-- [CONTEXTGUARD ${badge}] -->\n`;
|
|
111
|
+
const isBlocked = ['BLOCKED_BINARY', 'BLOCKED_LOCKFILE', 'BLOCKED_MINIFIED', 'ERROR'].includes(result.status);
|
|
112
|
+
return {
|
|
113
|
+
content: [{
|
|
114
|
+
type: 'text',
|
|
115
|
+
text: isBlocked
|
|
116
|
+
? `${badge}\n\n${result.content || result.error || result.reason}`
|
|
117
|
+
: header + result.content
|
|
118
|
+
}],
|
|
119
|
+
isError: isBlocked
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
return {
|
|
124
|
+
content: [{ type: 'text', text: `❌ [CONTEXTGUARD ERROR] ${err.message}` }],
|
|
125
|
+
isError: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
// ─── Tool: inspect_outline ────────────────────────────────────────────────────
|
|
130
|
+
server.registerTool('inspect_outline', {
|
|
131
|
+
title: 'Inspect File Outline',
|
|
132
|
+
description: [
|
|
133
|
+
'Returns a structural outline (classes, interfaces, functions, types, signals) of a source file.',
|
|
134
|
+
'This is a zero-cost, <5ms operation using the Tier 0 local AST skeletonizer.',
|
|
135
|
+
'Supports: TypeScript, JavaScript, Python, Go, Rust, Java, C#, Svelte 5, Vue 3, Angular, Astro.',
|
|
136
|
+
'Use this to navigate large files before calling read_file_safe with targeted line ranges.',
|
|
137
|
+
'Returns null if the file format is not supported for structural extraction.'
|
|
138
|
+
].join('\n'),
|
|
139
|
+
inputSchema: {
|
|
140
|
+
file_path: z.string().describe('Absolute or relative path to the source file.')
|
|
141
|
+
}
|
|
142
|
+
}, async ({ file_path }) => {
|
|
143
|
+
try {
|
|
144
|
+
const resolved = path.resolve(process.cwd(), file_path);
|
|
145
|
+
if (!fs.existsSync(resolved)) {
|
|
146
|
+
return {
|
|
147
|
+
content: [{ type: 'text', text: `⚠️ File not found: ${file_path}` }],
|
|
148
|
+
isError: true
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const ext = path.extname(resolved);
|
|
152
|
+
const langKey = isSupportedExtension(ext);
|
|
153
|
+
if (!langKey) {
|
|
154
|
+
return {
|
|
155
|
+
content: [{
|
|
156
|
+
type: 'text',
|
|
157
|
+
text: `ℹ️ [CONTEXTGUARD] File format "${ext}" is not supported for structural outline extraction.\nSupported: .ts, .tsx, .js, .jsx, .py, .go, .rs, .java, .cs, .svelte, .vue, .astro`
|
|
158
|
+
}]
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const raw = fs.readFileSync(resolved, 'utf-8');
|
|
162
|
+
const stat = fs.statSync(resolved);
|
|
163
|
+
const totalLines = raw.split('\n').length;
|
|
164
|
+
const skeleton = extractCodeSkeleton(raw, ext);
|
|
165
|
+
if (!skeleton) {
|
|
166
|
+
return {
|
|
167
|
+
content: [{
|
|
168
|
+
type: 'text',
|
|
169
|
+
text: `ℹ️ [CONTEXTGUARD] No structural declarations found in "${path.basename(file_path)}" (${totalLines} lines).`
|
|
170
|
+
}]
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
content: [{
|
|
175
|
+
type: 'text',
|
|
176
|
+
text: [
|
|
177
|
+
`<!-- [CONTEXTGUARD OUTLINE] ${path.basename(file_path)} · ${totalLines} lines · ${(stat.size / 1024).toFixed(1)} KB -->`,
|
|
178
|
+
`<!-- Use read_file_safe(file_path, start_line=N, end_line=M) to read any section. -->`,
|
|
179
|
+
'',
|
|
180
|
+
skeleton
|
|
181
|
+
].join('\n')
|
|
182
|
+
}]
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
return {
|
|
187
|
+
content: [{ type: 'text', text: `❌ [CONTEXTGUARD ERROR] ${err.message}` }],
|
|
188
|
+
isError: true
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
// ─── Tool: grep_distilled ─────────────────────────────────────────────────────
|
|
193
|
+
server.registerTool('grep_distilled', {
|
|
194
|
+
title: 'Grep (Distilled)',
|
|
195
|
+
description: [
|
|
196
|
+
'Searches for a pattern in files and returns only the structural outline of matching files,',
|
|
197
|
+
'not the full content. Prevents context flooding when searching across a large codebase.',
|
|
198
|
+
'For each matching file, returns the filename, matching lines, and the structural skeleton.',
|
|
199
|
+
'Pattern supports ripgrep syntax (fixed strings by default, pass is_regex=true for regex).',
|
|
200
|
+
'Results are capped at 20 files to keep context manageable.'
|
|
201
|
+
].join('\n'),
|
|
202
|
+
inputSchema: {
|
|
203
|
+
pattern: z.string().describe('Search pattern (string or regex if is_regex=true).'),
|
|
204
|
+
directory: z.string().optional().describe('Directory to search in. Defaults to current working directory.'),
|
|
205
|
+
include: z.string().optional().describe('Glob to filter files (e.g. "*.ts", "src/**/*.py"). Defaults to all text files.'),
|
|
206
|
+
is_regex: z.boolean().optional().describe('Treat pattern as a regex. Default false (fixed string search).')
|
|
207
|
+
}
|
|
208
|
+
}, async ({ pattern, directory, include, is_regex }) => {
|
|
209
|
+
try {
|
|
210
|
+
const searchDir = directory ? path.resolve(process.cwd(), directory) : process.cwd();
|
|
211
|
+
if (!fs.existsSync(searchDir)) {
|
|
212
|
+
return {
|
|
213
|
+
content: [{ type: 'text', text: `⚠️ Directory not found: ${directory}` }],
|
|
214
|
+
isError: true
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
// Build ripgrep command
|
|
218
|
+
const rgArgs = [
|
|
219
|
+
'--line-number',
|
|
220
|
+
'--with-filename',
|
|
221
|
+
'--no-heading',
|
|
222
|
+
'--color=never',
|
|
223
|
+
'--max-count=5', // max 5 matches per file
|
|
224
|
+
'-l' // list matching files first
|
|
225
|
+
];
|
|
226
|
+
if (!is_regex)
|
|
227
|
+
rgArgs.push('--fixed-strings');
|
|
228
|
+
if (include)
|
|
229
|
+
rgArgs.push('--glob', include);
|
|
230
|
+
rgArgs.push('--', pattern, searchDir);
|
|
231
|
+
let matchingFiles = [];
|
|
232
|
+
try {
|
|
233
|
+
const output = execSync(`rg ${rgArgs.map(a => JSON.stringify(a)).join(' ')}`, {
|
|
234
|
+
encoding: 'utf-8',
|
|
235
|
+
maxBuffer: 1024 * 512
|
|
236
|
+
});
|
|
237
|
+
matchingFiles = output.trim().split('\n').filter(Boolean).slice(0, 20);
|
|
238
|
+
}
|
|
239
|
+
catch (rgErr) {
|
|
240
|
+
// rg exits with 1 if no matches
|
|
241
|
+
if (rgErr.status === 1) {
|
|
242
|
+
return {
|
|
243
|
+
content: [{ type: 'text', text: `ℹ️ [CONTEXTGUARD GREP] No matches for "${pattern}" in ${searchDir}` }]
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
// rg not installed — fall back to a Node.js glob scan
|
|
247
|
+
return {
|
|
248
|
+
content: [{ type: 'text', text: `⚠️ ripgrep (rg) is not available. Install it with: brew install ripgrep\nCannot perform distilled grep without rg.` }],
|
|
249
|
+
isError: true
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
if (matchingFiles.length === 0) {
|
|
253
|
+
return {
|
|
254
|
+
content: [{ type: 'text', text: `ℹ️ [CONTEXTGUARD GREP] No matches for "${pattern}"` }]
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
// For each matching file: get matching lines + structural outline
|
|
258
|
+
const results = [
|
|
259
|
+
`<!-- [CONTEXTGUARD GREP] Pattern: "${pattern}" | ${matchingFiles.length} matching files -->`,
|
|
260
|
+
''
|
|
261
|
+
];
|
|
262
|
+
for (const filePath of matchingFiles) {
|
|
263
|
+
const ext = path.extname(filePath);
|
|
264
|
+
const relPath = path.relative(process.cwd(), filePath);
|
|
265
|
+
// Get matching lines with context
|
|
266
|
+
let matchLines = '';
|
|
267
|
+
try {
|
|
268
|
+
const matchArgs = [
|
|
269
|
+
'--line-number', '--no-heading', '--color=never',
|
|
270
|
+
'--max-count=5', '--context=1'
|
|
271
|
+
];
|
|
272
|
+
if (!is_regex)
|
|
273
|
+
matchArgs.push('--fixed-strings');
|
|
274
|
+
if (include)
|
|
275
|
+
matchArgs.push('--glob', include);
|
|
276
|
+
matchArgs.push('--', pattern, filePath);
|
|
277
|
+
matchLines = execSync(`rg ${matchArgs.map(a => JSON.stringify(a)).join(' ')}`, {
|
|
278
|
+
encoding: 'utf-8',
|
|
279
|
+
maxBuffer: 1024 * 64
|
|
280
|
+
}).trim();
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
matchLines = '(error reading match lines)';
|
|
284
|
+
}
|
|
285
|
+
// Get structural outline
|
|
286
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
287
|
+
const skeleton = extractCodeSkeleton(raw, ext);
|
|
288
|
+
const stat = fs.statSync(filePath);
|
|
289
|
+
const totalLines = raw.split('\n').length;
|
|
290
|
+
results.push(`### ${relPath} (${totalLines} lines, ${(stat.size / 1024).toFixed(1)} KB)`);
|
|
291
|
+
results.push('**Matches:**');
|
|
292
|
+
results.push('```');
|
|
293
|
+
results.push(matchLines);
|
|
294
|
+
results.push('```');
|
|
295
|
+
if (skeleton) {
|
|
296
|
+
results.push('**Structural outline:**');
|
|
297
|
+
results.push('```');
|
|
298
|
+
results.push(skeleton);
|
|
299
|
+
results.push('```');
|
|
300
|
+
}
|
|
301
|
+
results.push('');
|
|
302
|
+
}
|
|
303
|
+
if (matchingFiles.length === 20) {
|
|
304
|
+
results.push('> ⚠️ Results capped at 20 files. Narrow your search with a more specific pattern or --include glob.');
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
content: [{ type: 'text', text: results.join('\n') }]
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
return {
|
|
312
|
+
content: [{ type: 'text', text: `❌ [CONTEXTGUARD ERROR] ${err.message}` }],
|
|
313
|
+
isError: true
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
// ─── Start ─────────────────────────────────────────────────────────────────────
|
|
318
|
+
async function main() {
|
|
319
|
+
const transport = new StdioServerTransport();
|
|
320
|
+
await server.connect(transport);
|
|
321
|
+
// Log to stderr — never to stdout (would corrupt JSON-RPC channel)
|
|
322
|
+
process.stderr.write(`[ContextGuard MCP] Server v${SERVER_VERSION} running on stdio\n`);
|
|
323
|
+
}
|
|
324
|
+
main().catch((err) => {
|
|
325
|
+
process.stderr.write(`[ContextGuard MCP] Fatal error: ${err.message}\n`);
|
|
326
|
+
process.exit(1);
|
|
327
|
+
});
|
|
328
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../bin/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.test.d.ts","sourceRoot":"","sources":["../../tests/mcp-server.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Integration Tests (Phase 2)
|
|
3
|
+
* Tests the ContextGuard MCP server by spawning it as a child process
|
|
4
|
+
* and sending JSON-RPC 2.0 messages over stdin/stdout.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, before, after } from 'node:test';
|
|
7
|
+
import assert from 'node:assert';
|
|
8
|
+
import { spawn } from 'node:child_process';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import os from 'node:os';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const MCP_SERVER_BIN = path.resolve(__dirname, '../../dist/bin/mcp-server.js');
|
|
15
|
+
function sendRequest(proc, request) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
let buffer = '';
|
|
18
|
+
const onData = (chunk) => {
|
|
19
|
+
buffer += chunk.toString();
|
|
20
|
+
const lines = buffer.split('\n');
|
|
21
|
+
for (const line of lines) {
|
|
22
|
+
if (!line.trim())
|
|
23
|
+
continue;
|
|
24
|
+
try {
|
|
25
|
+
const parsed = JSON.parse(line);
|
|
26
|
+
if (parsed.id === request.id) {
|
|
27
|
+
proc.stdout.removeListener('data', onData);
|
|
28
|
+
resolve(parsed);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// partial or unrelated line — continue
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
buffer = lines[lines.length - 1] ?? '';
|
|
37
|
+
};
|
|
38
|
+
proc.stdout.on('data', onData);
|
|
39
|
+
proc.on('error', reject);
|
|
40
|
+
proc.stdin.write(JSON.stringify(request) + '\n');
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
proc.stdout.removeListener('data', onData);
|
|
43
|
+
reject(new Error(`Timeout waiting for response to request id=${request.id}`));
|
|
44
|
+
}, 5000);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// ─── Test Suite ───────────────────────────────────────────────────────────────
|
|
48
|
+
describe('ContextGuard MCP Server (Phase 2)', () => {
|
|
49
|
+
let proc;
|
|
50
|
+
let nextId = 1;
|
|
51
|
+
const req = (method, params) => ({
|
|
52
|
+
jsonrpc: '2.0',
|
|
53
|
+
id: nextId++,
|
|
54
|
+
method,
|
|
55
|
+
params
|
|
56
|
+
});
|
|
57
|
+
before(() => {
|
|
58
|
+
proc = spawn('node', [MCP_SERVER_BIN], {
|
|
59
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
60
|
+
});
|
|
61
|
+
proc.stderr.on('data', (d) => {
|
|
62
|
+
// Suppress server startup messages in test output
|
|
63
|
+
void d;
|
|
64
|
+
});
|
|
65
|
+
// Give the server a moment to initialize
|
|
66
|
+
return new Promise((r) => setTimeout(r, 300));
|
|
67
|
+
});
|
|
68
|
+
after(() => {
|
|
69
|
+
proc.stdin.end();
|
|
70
|
+
proc.kill();
|
|
71
|
+
});
|
|
72
|
+
// ── Initialization ──────────────────────────────────────────────────────────
|
|
73
|
+
it('should respond to initialize handshake', async () => {
|
|
74
|
+
const res = await sendRequest(proc, req('initialize', {
|
|
75
|
+
protocolVersion: '2024-11-05',
|
|
76
|
+
capabilities: {},
|
|
77
|
+
clientInfo: { name: 'test-client', version: '0.1.0' }
|
|
78
|
+
}));
|
|
79
|
+
assert.ok(!res.error, `Unexpected error: ${JSON.stringify(res.error)}`);
|
|
80
|
+
const result = res.result;
|
|
81
|
+
assert.ok(result.serverInfo, 'Must include serverInfo');
|
|
82
|
+
const info = result.serverInfo;
|
|
83
|
+
assert.strictEqual(info.name, 'context-guard');
|
|
84
|
+
assert.strictEqual(info.version, '1.2.0');
|
|
85
|
+
});
|
|
86
|
+
it('should list exactly 3 registered tools', async () => {
|
|
87
|
+
const res = await sendRequest(proc, req('tools/list'));
|
|
88
|
+
assert.ok(!res.error, `Unexpected error: ${JSON.stringify(res.error)}`);
|
|
89
|
+
const result = res.result;
|
|
90
|
+
const names = result.tools.map((t) => t.name);
|
|
91
|
+
assert.ok(names.includes('read_file_safe'), 'read_file_safe must be registered');
|
|
92
|
+
assert.ok(names.includes('inspect_outline'), 'inspect_outline must be registered');
|
|
93
|
+
assert.ok(names.includes('grep_distilled'), 'grep_distilled must be registered');
|
|
94
|
+
assert.strictEqual(names.length, 3, 'Must have exactly 3 tools');
|
|
95
|
+
});
|
|
96
|
+
// ── read_file_safe ──────────────────────────────────────────────────────────
|
|
97
|
+
it('read_file_safe: should return full content for a small file', async () => {
|
|
98
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-mcp-'));
|
|
99
|
+
const tmpFile = path.join(tmpDir, 'small.ts');
|
|
100
|
+
fs.writeFileSync(tmpFile, 'export const foo = 42;\nexport const bar = "hello";\n');
|
|
101
|
+
const res = await sendRequest(proc, req('tools/call', {
|
|
102
|
+
name: 'read_file_safe',
|
|
103
|
+
arguments: { file_path: tmpFile }
|
|
104
|
+
}));
|
|
105
|
+
assert.ok(!res.error, `Unexpected error: ${JSON.stringify(res.error)}`);
|
|
106
|
+
const result = res.result;
|
|
107
|
+
const text = result.content[0].text;
|
|
108
|
+
assert.ok(text.includes('PASSTHROUGH'), 'Must include PASSTHROUGH badge for small file');
|
|
109
|
+
assert.ok(text.includes('foo') || text.includes('bar'), 'Must include file content');
|
|
110
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
111
|
+
});
|
|
112
|
+
it('read_file_safe: should return AST skeleton for a large TypeScript file', async () => {
|
|
113
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-mcp-'));
|
|
114
|
+
const tmpFile = path.join(tmpDir, 'large.ts');
|
|
115
|
+
// Generate a file larger than 300 lines
|
|
116
|
+
const lines = [
|
|
117
|
+
'import path from "node:path";',
|
|
118
|
+
'import fs from "node:fs";',
|
|
119
|
+
'',
|
|
120
|
+
'export interface UserService {',
|
|
121
|
+
' getUser(id: string): Promise<User>;',
|
|
122
|
+
' createUser(data: CreateUserDto): Promise<User>;',
|
|
123
|
+
'}',
|
|
124
|
+
'',
|
|
125
|
+
'export class UserServiceImpl implements UserService {',
|
|
126
|
+
' async getUser(id: string): Promise<User> { return null as any; }',
|
|
127
|
+
' async createUser(data: CreateUserDto): Promise<User> { return null as any; }',
|
|
128
|
+
'}'
|
|
129
|
+
];
|
|
130
|
+
// Pad to >300 lines
|
|
131
|
+
while (lines.length < 310)
|
|
132
|
+
lines.push(` // line ${lines.length}`);
|
|
133
|
+
fs.writeFileSync(tmpFile, lines.join('\n'));
|
|
134
|
+
const res = await sendRequest(proc, req('tools/call', {
|
|
135
|
+
name: 'read_file_safe',
|
|
136
|
+
arguments: { file_path: tmpFile }
|
|
137
|
+
}));
|
|
138
|
+
assert.ok(!res.error, `Unexpected error: ${JSON.stringify(res.error)}`);
|
|
139
|
+
const result = res.result;
|
|
140
|
+
const text = result.content[0].text;
|
|
141
|
+
assert.ok(text.includes('SKELETON') || text.includes('SHUNT') || text.includes('UserService'), 'Must return skeleton or structural content for large file');
|
|
142
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
143
|
+
});
|
|
144
|
+
it('read_file_safe: should block a .wasm binary with isError=true', async () => {
|
|
145
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-mcp-'));
|
|
146
|
+
const wasmFile = path.join(tmpDir, 'module.wasm');
|
|
147
|
+
fs.writeFileSync(wasmFile, Buffer.from([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]));
|
|
148
|
+
const res = await sendRequest(proc, req('tools/call', {
|
|
149
|
+
name: 'read_file_safe',
|
|
150
|
+
arguments: { file_path: wasmFile }
|
|
151
|
+
}));
|
|
152
|
+
assert.ok(!res.error, 'JSON-RPC should not error — tool should handle it gracefully');
|
|
153
|
+
const result = res.result;
|
|
154
|
+
assert.ok(result.isError === true, 'isError must be true for blocked binary');
|
|
155
|
+
const text = result.content[0].text;
|
|
156
|
+
assert.ok(text.includes('BLOCKED') || text.includes('binario'), 'Must include block reason');
|
|
157
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
158
|
+
});
|
|
159
|
+
it('read_file_safe: should return a scoped slice when start_line/end_line given', async () => {
|
|
160
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-mcp-'));
|
|
161
|
+
const tmpFile = path.join(tmpDir, 'ranged.ts');
|
|
162
|
+
const content = Array.from({ length: 50 }, (_, i) => `// line ${i + 1}`).join('\n');
|
|
163
|
+
fs.writeFileSync(tmpFile, content);
|
|
164
|
+
const res = await sendRequest(proc, req('tools/call', {
|
|
165
|
+
name: 'read_file_safe',
|
|
166
|
+
arguments: { file_path: tmpFile, start_line: 5, end_line: 10 }
|
|
167
|
+
}));
|
|
168
|
+
assert.ok(!res.error, `Unexpected error: ${JSON.stringify(res.error)}`);
|
|
169
|
+
const result = res.result;
|
|
170
|
+
const text = result.content[0].text;
|
|
171
|
+
assert.ok(text.includes('line 5') || text.includes('SLICE'), 'Must contain sliced content');
|
|
172
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
173
|
+
});
|
|
174
|
+
// ── inspect_outline ─────────────────────────────────────────────────────────
|
|
175
|
+
it('inspect_outline: should return structural outline for a TypeScript file', async () => {
|
|
176
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-mcp-'));
|
|
177
|
+
const tmpFile = path.join(tmpDir, 'service.ts');
|
|
178
|
+
fs.writeFileSync(tmpFile, [
|
|
179
|
+
'export interface AuthService {',
|
|
180
|
+
' login(email: string, password: string): Promise<string>;',
|
|
181
|
+
' logout(token: string): void;',
|
|
182
|
+
'}',
|
|
183
|
+
'',
|
|
184
|
+
'export class AuthServiceImpl implements AuthService {',
|
|
185
|
+
' async login(email: string, password: string): Promise<string> { return "token"; }',
|
|
186
|
+
' logout(token: string): void {}',
|
|
187
|
+
'}'
|
|
188
|
+
].join('\n'));
|
|
189
|
+
const res = await sendRequest(proc, req('tools/call', {
|
|
190
|
+
name: 'inspect_outline',
|
|
191
|
+
arguments: { file_path: tmpFile }
|
|
192
|
+
}));
|
|
193
|
+
assert.ok(!res.error, `Unexpected error: ${JSON.stringify(res.error)}`);
|
|
194
|
+
const result = res.result;
|
|
195
|
+
const text = result.content[0].text;
|
|
196
|
+
assert.ok(text.includes('AuthService') || text.includes('login'), 'Must include structural declarations');
|
|
197
|
+
assert.ok(text.includes('OUTLINE'), 'Must include OUTLINE badge');
|
|
198
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
199
|
+
});
|
|
200
|
+
// ── grep_distilled ──────────────────────────────────────────────────────────
|
|
201
|
+
it('grep_distilled: should return no-match message when pattern is not found', async () => {
|
|
202
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-mcp-'));
|
|
203
|
+
fs.writeFileSync(path.join(tmpDir, 'a.ts'), 'export const x = 1;');
|
|
204
|
+
const res = await sendRequest(proc, req('tools/call', {
|
|
205
|
+
name: 'grep_distilled',
|
|
206
|
+
arguments: { pattern: 'PATTERN_THAT_DOES_NOT_EXIST_XYZ123', directory: tmpDir }
|
|
207
|
+
}));
|
|
208
|
+
assert.ok(!res.error, `Unexpected error: ${JSON.stringify(res.error)}`);
|
|
209
|
+
const result = res.result;
|
|
210
|
+
const text = result.content[0].text;
|
|
211
|
+
assert.ok(text.includes('No matches') || text.includes('not available'), 'Must indicate no matches');
|
|
212
|
+
fs.rmSync(tmpDir, { recursive: true });
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
//# sourceMappingURL=mcp-server.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.test.js","sourceRoot":"","sources":["../../tests/mcp-server.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kevinbermudezc/context-guard",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Intelligent context admission control and token optimization for Claude Code, Cursor, and Agentic workflows.",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Intelligent context admission control and token optimization for Claude Code, Cursor, Windsurf, Antigravity, and Agentic AI workflows.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -10,19 +10,26 @@
|
|
|
10
10
|
"types": "./dist/src/index.d.ts",
|
|
11
11
|
"bin": {
|
|
12
12
|
"context-guard": "./dist/bin/context-guard.js",
|
|
13
|
-
"context-guard-hook": "./dist/bin/claude-hook.js"
|
|
13
|
+
"context-guard-hook": "./dist/bin/claude-hook.js",
|
|
14
|
+
"context-guard-mcp": "./dist/bin/mcp-server.js"
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"dist",
|
|
17
18
|
"README.md",
|
|
18
|
-
"LICENSE"
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"examples"
|
|
19
21
|
],
|
|
20
22
|
"devDependencies": {
|
|
21
23
|
"@types/node": "^22.13.9",
|
|
22
|
-
"typescript": "^7.0.2"
|
|
24
|
+
"typescript": "^7.0.2",
|
|
25
|
+
"zod": "^4.6.5"
|
|
23
26
|
},
|
|
24
27
|
"keywords": [
|
|
25
28
|
"claude-code",
|
|
29
|
+
"cursor",
|
|
30
|
+
"windsurf",
|
|
31
|
+
"mcp",
|
|
32
|
+
"model-context-protocol",
|
|
26
33
|
"pretooluse-hook",
|
|
27
34
|
"ai-agent",
|
|
28
35
|
"token-optimization",
|
|
@@ -43,6 +50,9 @@
|
|
|
43
50
|
"engines": {
|
|
44
51
|
"node": ">=18.0.0"
|
|
45
52
|
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@modelcontextprotocol/server": "2.2.0"
|
|
55
|
+
},
|
|
46
56
|
"scripts": {
|
|
47
57
|
"build": "tsc && chmod +x dist/bin/*.js",
|
|
48
58
|
"test": "pnpm run build && node --test dist/tests/**/*.test.js"
|