mcp-compression-proxy 1.0.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/CHANGELOG.md +97 -0
- package/LICENSE +21 -0
- package/README.md +842 -0
- package/dist/cli/commands.d.ts +25 -0
- package/dist/cli/commands.js +152 -0
- package/dist/cli/daemon.d.ts +4 -0
- package/dist/cli/daemon.js +336 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +269 -0
- package/dist/cli/ipc-client.d.ts +11 -0
- package/dist/cli/ipc-client.js +81 -0
- package/dist/cli/payload-interceptor.d.ts +6 -0
- package/dist/cli/payload-interceptor.js +49 -0
- package/dist/config/loader.d.ts +53 -0
- package/dist/config/loader.js +332 -0
- package/dist/config/schema.d.ts +164 -0
- package/dist/config/schema.js +127 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +821 -0
- package/dist/mcp/client-manager.d.ts +65 -0
- package/dist/mcp/client-manager.js +197 -0
- package/dist/services/compression-cache.d.ts +112 -0
- package/dist/services/compression-cache.js +238 -0
- package/dist/services/compression-persistence.d.ts +36 -0
- package/dist/services/compression-persistence.js +111 -0
- package/dist/services/compression-sampler.d.ts +89 -0
- package/dist/services/compression-sampler.js +171 -0
- package/dist/services/session-manager.d.ts +64 -0
- package/dist/services/session-manager.js +160 -0
- package/dist/services/stats-service.d.ts +101 -0
- package/dist/services/stats-service.js +246 -0
- package/dist/types/compression.d.ts +38 -0
- package/dist/types/compression.js +5 -0
- package/dist/types/index.d.ts +108 -0
- package/dist/types/index.js +2 -0
- package/dist/version.d.ts +11 -0
- package/dist/version.js +11 -0
- package/package.json +110 -0
package/README.md
ADDED
|
@@ -0,0 +1,842 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ποΈ MCP Compression Proxy
|
|
4
|
+
|
|
5
|
+
**Aggregate tools from multiple MCP servers with intelligent LLM-based description compression**
|
|
6
|
+
|
|
7
|
+
[![npm version][npm-version-badge]][npm-package]
|
|
8
|
+
[![npm downloads][npm-downloads-badge]][npm-package]
|
|
9
|
+
[![npm types][npm-types-badge]][npm-package]
|
|
10
|
+
[![License: MIT][license-badge]][license]
|
|
11
|
+
[![Node][node-badge]][nodejs]
|
|
12
|
+
[![MCP][mcp-badge]][mcp-protocol]
|
|
13
|
+
|
|
14
|
+
[![CI][ci-badge]][ci-workflow]
|
|
15
|
+
[![codecov][codecov-badge]][codecov]
|
|
16
|
+
[![CodeQL][codeql-badge]][codeql-workflow]
|
|
17
|
+
|
|
18
|
+
[![GitHub Stars][stars-badge]][stargazers]
|
|
19
|
+
[![GitHub Forks][forks-badge]][network]
|
|
20
|
+
[![GitHub Issues][issues-badge]][repo-issues]
|
|
21
|
+
[![GitHub Last Commit][commit-badge]][commits]
|
|
22
|
+
[![PRs Welcome][prs-badge]][contributing]
|
|
23
|
+
|
|
24
|
+
[Quick Start](#-quick-start) β’
|
|
25
|
+
[Features](#-features) β’
|
|
26
|
+
[mcp-cli](#οΈ-mcp-cli-progressive-tool-discovery) β’
|
|
27
|
+
[Configuration](#-configuration) β’
|
|
28
|
+
[FAQ](#-faq) β’
|
|
29
|
+
[Contributing](#-contributing)
|
|
30
|
+
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## π Table of Contents
|
|
36
|
+
|
|
37
|
+
- [What is MCP Compression Proxy?](#what-is-mcp-compression-proxy)
|
|
38
|
+
- [β¨ Features](#-features)
|
|
39
|
+
- [π Quick Start](#-quick-start)
|
|
40
|
+
- [π― Usage](#-usage)
|
|
41
|
+
- [β¨οΈ mcp-cli (Progressive Tool Discovery)](#οΈ-mcp-cli-progressive-tool-discovery)
|
|
42
|
+
- [π§ Configuration](#-configuration)
|
|
43
|
+
- [π‘ Best Practices](#-best-practices)
|
|
44
|
+
- [β FAQ](#-faq)
|
|
45
|
+
- [π§ͺ Testing](#-testing)
|
|
46
|
+
- [π€ Contributing](#-contributing)
|
|
47
|
+
- [π Support This Project](#-support-this-project)
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## What is MCP Compression Proxy?
|
|
52
|
+
|
|
53
|
+
A **Model Context Protocol (MCP) server** that solves two common problems:
|
|
54
|
+
|
|
55
|
+
1. **Multi-server aggregation**: Access tools from multiple MCP servers through a single connection
|
|
56
|
+
2. **Context optimization**: Reduce token consumption by 50-80% using intelligent LLM-based description compression
|
|
57
|
+
|
|
58
|
+
Instead of connecting to multiple MCP servers separately and consuming thousands of tokens on verbose tool descriptions, MCP Compression Proxy aggregates all your tools and compresses their descriptions intelligentlyβpreserving critical information while removing redundancy.
|
|
59
|
+
|
|
60
|
+
**Perfect for:**
|
|
61
|
+
- Users with many MCP servers (filesystem, GitHub, databases, etc.)
|
|
62
|
+
- AI agents working with limited context windows
|
|
63
|
+
- Anyone wanting to minimize token costs while maximizing tool availability
|
|
64
|
+
|
|
65
|
+
## β¨ Features
|
|
66
|
+
|
|
67
|
+
- **π Multi-Server Aggregation** - Access tools from multiple MCP servers through one connection
|
|
68
|
+
- **π€ LLM-Based Compression** - Intelligent description compression (50-80% token reduction)
|
|
69
|
+
- **πΎ Persistent Storage** - Compressed descriptions saved to disk and restored on restart
|
|
70
|
+
- **π Session-Based Expansion** - Independent expansion state per conversation
|
|
71
|
+
- **β‘ Parallel Initialization** - All servers connect in parallel with configurable timeouts
|
|
72
|
+
- **π― Selective Expansion** - Compress all tools, expand only what you need
|
|
73
|
+
- **π¦ Zero Config** - Works out-of-the-box with sensible defaults
|
|
74
|
+
- **π₯ Standard MCP** - Compatible with any MCP client (Claude Desktop, Cline, etc.)
|
|
75
|
+
|
|
76
|
+
## π Quick Start
|
|
77
|
+
|
|
78
|
+
### Prerequisites
|
|
79
|
+
|
|
80
|
+
- **Node.js 22+** installed on your system
|
|
81
|
+
- An **MCP-compatible client** (Claude Desktop, Cline, Continue.dev, etc.)
|
|
82
|
+
|
|
83
|
+
### 1. Install
|
|
84
|
+
|
|
85
|
+
**Option A: Install from npm** (recommended for most users):
|
|
86
|
+
```bash
|
|
87
|
+
npm install -g mcp-compression-proxy
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Option B: Install from source** (for development or latest features):
|
|
91
|
+
```bash
|
|
92
|
+
git clone https://github.com/kdpa-llc/mcp-compression-proxy.git
|
|
93
|
+
cd mcp-compression-proxy
|
|
94
|
+
npm install
|
|
95
|
+
npm run build
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 2. Configure MCP Client
|
|
99
|
+
|
|
100
|
+
Add to your MCP client configuration file:
|
|
101
|
+
|
|
102
|
+
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
103
|
+
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
104
|
+
|
|
105
|
+
**If installed via npm:**
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"mcpServers": {
|
|
109
|
+
"compression-proxy": {
|
|
110
|
+
"command": "mcp-compression-proxy",
|
|
111
|
+
"env": {
|
|
112
|
+
"LOG_LEVEL": "info"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**If installed from source:**
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"mcpServers": {
|
|
123
|
+
"compression-proxy": {
|
|
124
|
+
"command": "node",
|
|
125
|
+
"args": [
|
|
126
|
+
"/absolute/path/to/mcp-compression-proxy/dist/index.js"
|
|
127
|
+
],
|
|
128
|
+
"env": {
|
|
129
|
+
"LOG_LEVEL": "info"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 3. Configure Servers
|
|
137
|
+
|
|
138
|
+
Create a JSON configuration file to define which MCP servers to aggregate:
|
|
139
|
+
|
|
140
|
+
**Option 1: User-level config** (recommended for personal use)
|
|
141
|
+
- Location: `~/.mcp-compression-proxy/servers.json`
|
|
142
|
+
|
|
143
|
+
**Option 2: Project-level config** (recommended for team projects)
|
|
144
|
+
- Location: `./servers.json` (in the mcp-compression-proxy directory)
|
|
145
|
+
|
|
146
|
+
**Example configuration:**
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"mcpServers": [
|
|
151
|
+
{
|
|
152
|
+
"name": "filesystem",
|
|
153
|
+
"command": "npx",
|
|
154
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
|
|
155
|
+
"enabled": true
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "github",
|
|
159
|
+
"command": "npx",
|
|
160
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
161
|
+
"env": {
|
|
162
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
|
|
163
|
+
},
|
|
164
|
+
"enabled": true
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
> **Note:** No rebuild needed! Just edit the JSON file and restart your MCP client.
|
|
171
|
+
|
|
172
|
+
### 4. Restart Your MCP Client
|
|
173
|
+
|
|
174
|
+
Restart your MCP client (e.g., Claude Desktop) to load the new configuration. The proxy will automatically connect to all configured MCP servers and make their tools available.
|
|
175
|
+
|
|
176
|
+
## π― Usage
|
|
177
|
+
|
|
178
|
+
### Tool Naming
|
|
179
|
+
|
|
180
|
+
**Proxied tools** from your configured MCP servers use the format `serverName__toolName`:
|
|
181
|
+
- `filesystem__read_file`
|
|
182
|
+
- `filesystem__write_file`
|
|
183
|
+
- `github__create_issue`
|
|
184
|
+
|
|
185
|
+
**Management tools** (built-in) don't have a prefix and are listed below.
|
|
186
|
+
|
|
187
|
+
### Management Tools
|
|
188
|
+
|
|
189
|
+
| Tool | Description |
|
|
190
|
+
|------|-------------|
|
|
191
|
+
| `create_session` | Create a new session for independent tool expansion |
|
|
192
|
+
| `set_session` | Set the active session |
|
|
193
|
+
| `delete_session` | Delete a session |
|
|
194
|
+
| `clear_compressed_tools_cache` | Clear all cached compressed tool descriptions |
|
|
195
|
+
| `get_uncompressed_tools` | Get tools that need compression (batch processing) |
|
|
196
|
+
| `cache_compressed_tools` | Save compressed descriptions to cache (batch processing) |
|
|
197
|
+
| `compress_via_sampling` | Compress automatically using the client's own LLM (requires sampling support) |
|
|
198
|
+
| `expand_tool` | Expand a tool to show full description (session-specific) |
|
|
199
|
+
| `collapse_tool` | Collapse tool back to compressed description |
|
|
200
|
+
| `stats` | Return JSON summary of coverage, cache health, sessions, and per-server tool counts |
|
|
201
|
+
|
|
202
|
+
Use `stats` from your client (e.g., `mcp-compression-proxy__stats`) to sanity-check coverage. Optional inputs: `serverName` to scope to one backend and `detailLevel` (`summary` or `full`, default `summary`). The response includes coverage %, estimated token savings, cache state, active sessions, and per-server tool counts (respecting your exclude patterns).
|
|
203
|
+
|
|
204
|
+
#### Automatic Compression (MCP Sampling)
|
|
205
|
+
|
|
206
|
+
If your client supports [MCP sampling][mcp-sampling], the proxy can compress
|
|
207
|
+
descriptions by borrowing the client's own LLM β no API key, no second model
|
|
208
|
+
to configure, and no work for you beyond one tool call:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
mcp-compression-proxy__compress_via_sampling
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
It reads the uncompressed tools, asks the host to rewrite them, caches the
|
|
215
|
+
results, and reports before/after coverage. Call it again for the next batch
|
|
216
|
+
until nothing remains. Batches are sent one at a time, since a host may ask
|
|
217
|
+
you to approve each request.
|
|
218
|
+
|
|
219
|
+
Support varies by client β Cursor implements sampling; Claude Desktop and
|
|
220
|
+
Cline did not at the time of writing. On a client without it the tool returns
|
|
221
|
+
an error pointing at the manual `get_uncompressed_tools` β
|
|
222
|
+
`cache_compressed_tools` flow, which works everywhere.
|
|
223
|
+
|
|
224
|
+
### Workflow Example
|
|
225
|
+
|
|
226
|
+
#### 1. Before Compression
|
|
227
|
+
|
|
228
|
+
When you first ask your AI assistant about available tools:
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
User: What tools do you have?
|
|
232
|
+
|
|
233
|
+
AI: I have access to these tools:
|
|
234
|
+
- filesystem__read_file: Reads the complete contents of a file at the
|
|
235
|
+
specified path. The file must exist and be readable. Returns the file
|
|
236
|
+
contents as text. Supports absolute and relative paths. Maximum file
|
|
237
|
+
size is 10MB. Will throw an error if the file doesn't exist...
|
|
238
|
+
[~200 tokens for one tool]
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### 2. Enable Compression (One-Time Setup)
|
|
242
|
+
|
|
243
|
+
Ask your AI assistant to compress the descriptions:
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
User: Use the mcp-compression-proxy tools to compress tool descriptions and save model context
|
|
247
|
+
|
|
248
|
+
AI: I'll compress the tool descriptions:
|
|
249
|
+
1. Getting all tools via get_uncompressed_tools...
|
|
250
|
+
2. Compressing descriptions intelligently...
|
|
251
|
+
3. Saving compressed versions via cache_compressed_tools...
|
|
252
|
+
|
|
253
|
+
Done! Tool descriptions are now compressed and saved to cache.
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
#### 3. After Compression
|
|
257
|
+
|
|
258
|
+
The same request now uses far fewer tokens:
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
User: What tools do you have?
|
|
262
|
+
|
|
263
|
+
AI: I have access to these tools:
|
|
264
|
+
- filesystem__read_file: Read file contents (text, max 10MB)
|
|
265
|
+
- filesystem__write_file: Write/overwrite file
|
|
266
|
+
- github__create_issue: Create GitHub issue
|
|
267
|
+
[~30 tokens for one tool]
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Result**: ~70% reduction in tokens for tool listings!
|
|
271
|
+
|
|
272
|
+
#### 4. Persistent Storage
|
|
273
|
+
|
|
274
|
+
Compressed descriptions are automatically saved to disk at `~/.mcp-compression-proxy/cache.json` and loaded on server restart. No need to re-compress after restarting!
|
|
275
|
+
|
|
276
|
+
**To clear the cache if needed:**
|
|
277
|
+
```bash
|
|
278
|
+
# If installed via npm
|
|
279
|
+
mcp-compression-proxy --clear-cache
|
|
280
|
+
|
|
281
|
+
# If installed from source
|
|
282
|
+
node dist/index.js --clear-cache
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
> **π‘ Tip**: After setting up, simply tell your AI: *"Compress the tool descriptions to save context"* and it will handle the rest!
|
|
286
|
+
|
|
287
|
+
## β¨οΈ mcp-cli (Progressive Tool Discovery)
|
|
288
|
+
|
|
289
|
+
The package also installs `mcp-cli`, a second entry point for agents that
|
|
290
|
+
would rather *shell out* than hold every tool definition in context. Instead
|
|
291
|
+
of loading all tools up front, the agent lists or searches for what it needs
|
|
292
|
+
and pulls the full schema only for the tool it is about to call.
|
|
293
|
+
|
|
294
|
+
A background daemon keeps warm connections to the backend MCP servers, so
|
|
295
|
+
each command is a short IPC round-trip rather than a fresh server startup.
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
mcp-cli tools # List all tools (compressed)
|
|
299
|
+
mcp-cli search <query> # Search tools by name/description
|
|
300
|
+
mcp-cli info <server>/<tool> # Full schema for one tool
|
|
301
|
+
mcp-cli call <server>/<tool> '<json>' # Execute a tool
|
|
302
|
+
mcp-cli stats # Compression statistics
|
|
303
|
+
|
|
304
|
+
mcp-cli daemon start # Start the background daemon
|
|
305
|
+
mcp-cli daemon status # Show daemon status
|
|
306
|
+
mcp-cli daemon stop # Stop the daemon
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
The daemon starts automatically on first use. Pass `--no-auto-start` to fail
|
|
310
|
+
fast instead when it is not already running.
|
|
311
|
+
|
|
312
|
+
`call` also accepts its JSON argument on stdin, which avoids shell quoting
|
|
313
|
+
problems with large payloads:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
echo '{"path": "/tmp/notes.md"}' | mcp-cli call filesystem/read_file
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### CLI Configuration
|
|
320
|
+
|
|
321
|
+
The optional `cli` block in `servers.json` tunes daemon behavior:
|
|
322
|
+
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"cli": {
|
|
326
|
+
"payloadThreshold": 500,
|
|
327
|
+
"autoStartDaemon": true,
|
|
328
|
+
"daemonLogLevel": "info"
|
|
329
|
+
},
|
|
330
|
+
"mcpServers": []
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
| Field | Type | Default | Description |
|
|
335
|
+
|-------|------|---------|-------------|
|
|
336
|
+
| `payloadThreshold` | number | `500` | Tool output longer than this many characters is written to a temp file and replaced with a reference, keeping large payloads out of the agent's context |
|
|
337
|
+
| `autoStartDaemon` | boolean | `true` | Start the daemon automatically when a command needs it |
|
|
338
|
+
| `daemonLogLevel` | string | `"info"` | Daemon log level (`debug`, `info`, `warn`, `error`) |
|
|
339
|
+
|
|
340
|
+
Daemon state lives in `~/.mcp-compression-proxy/` (socket, PID file, and
|
|
341
|
+
`daemon.log`), created with `0700` permissions since the control socket
|
|
342
|
+
accepts commands that execute downstream MCP tools.
|
|
343
|
+
|
|
344
|
+
## π§ Configuration
|
|
345
|
+
|
|
346
|
+
### Server Configuration
|
|
347
|
+
|
|
348
|
+
Create or edit your JSON configuration file at:
|
|
349
|
+
- `~/.mcp-compression-proxy/servers.json` (user-level), or
|
|
350
|
+
- `./servers.json` (project-level)
|
|
351
|
+
|
|
352
|
+
```json
|
|
353
|
+
{
|
|
354
|
+
"mcpServers": [
|
|
355
|
+
{
|
|
356
|
+
"name": "my-server",
|
|
357
|
+
"command": "command-to-run",
|
|
358
|
+
"args": ["arg1", "arg2"],
|
|
359
|
+
"env": {
|
|
360
|
+
"ENV_VAR": "value"
|
|
361
|
+
},
|
|
362
|
+
"enabled": true
|
|
363
|
+
}
|
|
364
|
+
]
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
#### Configuration Schema
|
|
369
|
+
|
|
370
|
+
**Root Level:**
|
|
371
|
+
| Field | Type | Required | Description |
|
|
372
|
+
|-------|------|----------|-------------|
|
|
373
|
+
| `mcpServers` | array | β
| Array of server configurations |
|
|
374
|
+
| `excludeTools` | string[] | β | Tool name patterns to exclude from tool list entirely (supports wildcards) |
|
|
375
|
+
| `noCompressTools` | string[] | β | Tool name patterns to never compress - descriptions pass through unchanged (supports wildcards) |
|
|
376
|
+
| `defaultTimeout` | number | β | Default timeout in seconds for all servers (default: 30). Can be overridden per-server. |
|
|
377
|
+
| `inheritEnv` | boolean \| string[] | β | Which of the proxy's environment variables backend servers inherit (default: `true`). Can be overridden per-server. |
|
|
378
|
+
| `compressionFallbackBehavior` | `"original"` \| `"blank"` | β | What to show for a tool that has not been compressed yet (default: `"original"`) |
|
|
379
|
+
|
|
380
|
+
**Server Configuration:**
|
|
381
|
+
| Field | Type | Required | Description |
|
|
382
|
+
|-------|------|----------|-------------|
|
|
383
|
+
| `name` | string | β
| Unique server identifier |
|
|
384
|
+
| `command` | string | β
| Command to execute |
|
|
385
|
+
| `args` | string[] | β | Command arguments |
|
|
386
|
+
| `env` | object | β | Environment variables |
|
|
387
|
+
| `inheritEnv` | boolean \| string[] | β | Overrides the root-level `inheritEnv` for this server |
|
|
388
|
+
| `enabled` | boolean | β | Enable/disable server (default: true) |
|
|
389
|
+
| `timeout` | number | β | Server-specific timeout in seconds (overrides `defaultTimeout`) |
|
|
390
|
+
|
|
391
|
+
#### Environment Variable Expansion
|
|
392
|
+
|
|
393
|
+
Use `${VAR_NAME}` syntax to reference environment variables:
|
|
394
|
+
|
|
395
|
+
```json
|
|
396
|
+
{
|
|
397
|
+
"mcpServers": [
|
|
398
|
+
{
|
|
399
|
+
"name": "github",
|
|
400
|
+
"command": "npx",
|
|
401
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
402
|
+
"env": {
|
|
403
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}",
|
|
404
|
+
"GITHUB_ORG": "${MY_GITHUB_ORG}"
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Variables are expanded at runtime from your shell environment.
|
|
412
|
+
|
|
413
|
+
Two extra forms are supported:
|
|
414
|
+
|
|
415
|
+
| Syntax | Meaning |
|
|
416
|
+
|--------|---------|
|
|
417
|
+
| `${VAR}` | Substitutes `VAR`, or an empty string with a warning if it is not set |
|
|
418
|
+
| `${VAR:-fallback}` | Substitutes `VAR`, or `fallback` when unset or empty |
|
|
419
|
+
| `$${VAR}` | Escapes the expansion β produces the literal text `${VAR}` |
|
|
420
|
+
|
|
421
|
+
If a `${VAR}` reference cannot be resolved, the proxy logs a warning naming
|
|
422
|
+
the variable. An unset variable becomes an empty string, which downstream
|
|
423
|
+
servers usually report as an authentication failure rather than a config
|
|
424
|
+
error, so check the startup log first when a server rejects valid-looking
|
|
425
|
+
credentials.
|
|
426
|
+
|
|
427
|
+
#### What Backend Servers Inherit
|
|
428
|
+
|
|
429
|
+
Backend servers inherit the proxy's full environment by default, so variables
|
|
430
|
+
you exported in your shell are visible to them without being listed in `env`.
|
|
431
|
+
Entries in `env` always take precedence over inherited values.
|
|
432
|
+
|
|
433
|
+
Narrow this with `inheritEnv` when a server should not see unrelated secrets:
|
|
434
|
+
|
|
435
|
+
```json
|
|
436
|
+
{
|
|
437
|
+
"inheritEnv": ["HOME", "PATH", "LANG"],
|
|
438
|
+
"mcpServers": [
|
|
439
|
+
{
|
|
440
|
+
"name": "trusted",
|
|
441
|
+
"command": "npx",
|
|
442
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
443
|
+
"inheritEnv": true
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"name": "untrusted",
|
|
447
|
+
"command": "some-third-party-server",
|
|
448
|
+
"inheritEnv": false,
|
|
449
|
+
"env": { "API_KEY": "${THIRD_PARTY_KEY}" }
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
| Value | Effect |
|
|
456
|
+
|-------|--------|
|
|
457
|
+
| `true` (default) | Pass the proxy's full environment through |
|
|
458
|
+
| `false` | Pass only the stdio transport's safe defaults (`PATH`, `HOME`, `SHELL`, β¦) |
|
|
459
|
+
| `string[]` | Pass only the named variables, plus the transport's safe defaults |
|
|
460
|
+
|
|
461
|
+
#### Uncompressed Tool Descriptions
|
|
462
|
+
|
|
463
|
+
Before a tool has been compressed, the proxy shows its original description.
|
|
464
|
+
Set `compressionFallbackBehavior` to `"blank"` to show nothing instead, so
|
|
465
|
+
uncompressed tools cost no context while you work through them:
|
|
466
|
+
|
|
467
|
+
```json
|
|
468
|
+
{
|
|
469
|
+
"compressionFallbackBehavior": "blank",
|
|
470
|
+
"mcpServers": []
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
This affects only tools with no cached compressed description. Compressed
|
|
475
|
+
tools, expanded tools, and anything matching `noCompressTools` are unchanged.
|
|
476
|
+
|
|
477
|
+
#### Server Initialization and Timeouts
|
|
478
|
+
|
|
479
|
+
The proxy initializes all configured MCP servers in **parallel** before becoming ready. Each server connection is wrapped with a timeout to prevent indefinite hanging:
|
|
480
|
+
|
|
481
|
+
- **Default timeout**: 30 seconds (if not specified)
|
|
482
|
+
- **Global timeout**: Set `defaultTimeout` in config to change the default for all servers
|
|
483
|
+
- **Per-server timeout**: Set `timeout` on individual servers to override the default
|
|
484
|
+
|
|
485
|
+
```json
|
|
486
|
+
{
|
|
487
|
+
"defaultTimeout": 60,
|
|
488
|
+
"mcpServers": [
|
|
489
|
+
{
|
|
490
|
+
"name": "fast-server",
|
|
491
|
+
"command": "npx",
|
|
492
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
"name": "slow-server",
|
|
496
|
+
"command": "python",
|
|
497
|
+
"args": ["slow_mcp_server.py"],
|
|
498
|
+
"timeout": 120
|
|
499
|
+
}
|
|
500
|
+
]
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
**Behavior:**
|
|
505
|
+
- All servers initialize in parallel (not sequentially)
|
|
506
|
+
- If a server exceeds its timeout, it's marked as failed but doesn't block other servers
|
|
507
|
+
- The proxy reports ready only after all servers have either connected or timed out
|
|
508
|
+
- This ensures all available tools are loaded before the MCP client can query them
|
|
509
|
+
|
|
510
|
+
**Why this matters:** Without proper timeout handling, a single hanging server could make the entire proxy unresponsive.
|
|
511
|
+
|
|
512
|
+
#### Tool Filtering Patterns
|
|
513
|
+
|
|
514
|
+
**Exclude Tools** - Remove tools from the tool list entirely:
|
|
515
|
+
|
|
516
|
+
Use the `excludeTools` field to filter out unwanted tools using wildcard patterns (case-insensitive):
|
|
517
|
+
|
|
518
|
+
```json
|
|
519
|
+
{
|
|
520
|
+
"mcpServers": [...],
|
|
521
|
+
"excludeTools": [
|
|
522
|
+
"github__delete_*", // Exclude all GitHub delete tools
|
|
523
|
+
"*__experimental*", // Exclude all experimental tools
|
|
524
|
+
"filesystem__write_*", // Exclude filesystem write tools
|
|
525
|
+
"set_*" // Exclude management tools starting with set_
|
|
526
|
+
]
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
**No-Compress Tools** - Keep tools but never compress their descriptions:
|
|
531
|
+
|
|
532
|
+
Use the `noCompressTools` field to bypass compression for specific tools (descriptions pass through unchanged):
|
|
533
|
+
|
|
534
|
+
```json
|
|
535
|
+
{
|
|
536
|
+
"mcpServers": [...],
|
|
537
|
+
"noCompressTools": [
|
|
538
|
+
"filesystem__*", // Never compress filesystem tool descriptions
|
|
539
|
+
"*__help", // Never compress help commands
|
|
540
|
+
"github__search_*" // Never compress GitHub search tools
|
|
541
|
+
]
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
**Pattern Examples:**
|
|
546
|
+
- `"serverName__*"` - All tools from specific server
|
|
547
|
+
- `"*__toolPattern*"` - Tools matching pattern from any server
|
|
548
|
+
- `"exact_tool_name"` - Exact tool name match
|
|
549
|
+
|
|
550
|
+
**Use Cases:**
|
|
551
|
+
- **excludeTools**: Remove dangerous tools, unwanted features, or tools not relevant to your workflow
|
|
552
|
+
- **noCompressTools**: Preserve detailed descriptions for complex tools where compression might lose important information
|
|
553
|
+
|
|
554
|
+
#### Configuration Aggregation
|
|
555
|
+
|
|
556
|
+
Both config files are loaded and combined:
|
|
557
|
+
|
|
558
|
+
1. Load user config (`~/.mcp-compression-proxy/servers.json`)
|
|
559
|
+
2. Load project config (`./servers.json`)
|
|
560
|
+
3. Aggregate servers from both configs
|
|
561
|
+
4. Aggregate exclude and noCompress patterns from both configs
|
|
562
|
+
5. Apply exclude patterns to filter tools
|
|
563
|
+
6. Apply noCompress patterns to bypass compression
|
|
564
|
+
|
|
565
|
+
This allows:
|
|
566
|
+
- Personal defaults in user config
|
|
567
|
+
- Team/project-specific servers in project config
|
|
568
|
+
- Fine-grained tool filtering with exclude patterns
|
|
569
|
+
- Selective compression bypass with noCompress patterns
|
|
570
|
+
|
|
571
|
+
### Environment Variables
|
|
572
|
+
|
|
573
|
+
**For the compression proxy** (set in your MCP client config):
|
|
574
|
+
- `LOG_LEVEL` - Logging level (debug, info, warn, error). Default: `info`
|
|
575
|
+
|
|
576
|
+
**For MCP servers** (set in `servers.json` using `${VAR_NAME}` syntax):
|
|
577
|
+
- `GITHUB_TOKEN` - GitHub personal access token (if using GitHub MCP server)
|
|
578
|
+
- Any other environment variables required by your configured MCP servers
|
|
579
|
+
|
|
580
|
+
See [Environment Variable Expansion](#environment-variable-expansion) for details on using variables in your server configuration.
|
|
581
|
+
|
|
582
|
+
### Command-Line Options
|
|
583
|
+
|
|
584
|
+
**`--clear-cache`** - Clear the persistent compression cache and exit
|
|
585
|
+
|
|
586
|
+
```bash
|
|
587
|
+
# If installed via npm
|
|
588
|
+
mcp-compression-proxy --clear-cache
|
|
589
|
+
|
|
590
|
+
# If installed from source
|
|
591
|
+
node dist/index.js --clear-cache
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Debugging
|
|
595
|
+
|
|
596
|
+
**1. Enable debug logging** in your MCP client config:
|
|
597
|
+
|
|
598
|
+
```json
|
|
599
|
+
{
|
|
600
|
+
"mcpServers": {
|
|
601
|
+
"compression-proxy": {
|
|
602
|
+
"command": "mcp-compression-proxy",
|
|
603
|
+
"env": {
|
|
604
|
+
"LOG_LEVEL": "debug"
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
**2. View logs** (for Claude Desktop):
|
|
612
|
+
- **macOS**: `~/Library/Logs/Claude/mcp*.log`
|
|
613
|
+
- **Windows**: `%APPDATA%\Claude\Logs\mcp*.log`
|
|
614
|
+
|
|
615
|
+
**3. Check for common issues:**
|
|
616
|
+
- Ensure all configured MCP servers are accessible and properly configured
|
|
617
|
+
- Verify environment variables are correctly expanded
|
|
618
|
+
- Check that Node.js version is 18 or higher
|
|
619
|
+
|
|
620
|
+
## π‘ Best Practices
|
|
621
|
+
|
|
622
|
+
### Good Compression
|
|
623
|
+
|
|
624
|
+
**Preserves**:
|
|
625
|
+
- Core functionality
|
|
626
|
+
- Key parameters
|
|
627
|
+
- Critical constraints
|
|
628
|
+
- Return types
|
|
629
|
+
|
|
630
|
+
**Removes**:
|
|
631
|
+
- Verbose explanations
|
|
632
|
+
- Redundant phrases
|
|
633
|
+
- Non-critical examples
|
|
634
|
+
- Marketing language
|
|
635
|
+
|
|
636
|
+
### Example
|
|
637
|
+
|
|
638
|
+
**Original** (42 tokens):
|
|
639
|
+
```
|
|
640
|
+
"Searches for files in the specified directory and its subdirectories using
|
|
641
|
+
glob patterns. Supports wildcards like *, **, and ?. Returns an array of
|
|
642
|
+
matching file paths. Case-sensitive by default."
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
**Compressed** (12 tokens):
|
|
646
|
+
```
|
|
647
|
+
"Search files by glob pattern (*, **, ?), case-sensitive, returns paths"
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
## β FAQ
|
|
651
|
+
|
|
652
|
+
<details>
|
|
653
|
+
<summary><strong>Q: What MCP clients are supported?</strong></summary>
|
|
654
|
+
<p>Any MCP-compatible client: Claude Desktop, Cline, Continue.dev, or custom agents.</p>
|
|
655
|
+
</details>
|
|
656
|
+
|
|
657
|
+
<details>
|
|
658
|
+
<summary><strong>Q: How much context does compression save?</strong></summary>
|
|
659
|
+
<p>Typically 50-80% reduction in token count for tool listings while preserving critical information.</p>
|
|
660
|
+
</details>
|
|
661
|
+
|
|
662
|
+
<details>
|
|
663
|
+
<summary><strong>Q: Do I need to restart after adding servers?</strong></summary>
|
|
664
|
+
<p>Yes, restart your MCP client to load the new configuration. No rebuild needed when using JSON configuration.</p>
|
|
665
|
+
</details>
|
|
666
|
+
|
|
667
|
+
<details>
|
|
668
|
+
<summary><strong>Q: Can I use multiple MCP servers?</strong></summary>
|
|
669
|
+
<p>Yes! That's the primary use case. Add as many as you need in your <code>servers.json</code> configuration file.</p>
|
|
670
|
+
</details>
|
|
671
|
+
|
|
672
|
+
<details>
|
|
673
|
+
<summary><strong>Q: Is compression permanent?</strong></summary>
|
|
674
|
+
<p>Compressed descriptions are persisted to disk at <code>~/.mcp-compression-proxy/cache.json</code> and automatically restored on server restart. Session-based expansions are temporary and reset per session.</p>
|
|
675
|
+
</details>
|
|
676
|
+
|
|
677
|
+
<details>
|
|
678
|
+
<summary><strong>Q: Where is the compression cache stored?</strong></summary>
|
|
679
|
+
<p>Cache is stored at <code>~/.mcp-compression-proxy/cache.json</code>. Use <code>--clear-cache</code> flag to clear it if needed.</p>
|
|
680
|
+
</details>
|
|
681
|
+
|
|
682
|
+
<details>
|
|
683
|
+
<summary><strong>Q: Works with local LLMs?</strong></summary>
|
|
684
|
+
<p>Yes! Works with any MCP-compatible setup, including local models.</p>
|
|
685
|
+
</details>
|
|
686
|
+
|
|
687
|
+
<details>
|
|
688
|
+
<summary><strong>Q: How do I add a new MCP server?</strong></summary>
|
|
689
|
+
<p>Edit your <code>servers.json</code> configuration file (in <code>~/.mcp-compression-proxy/</code> or project root), add your server config, and restart your MCP client. No rebuild needed.</p>
|
|
690
|
+
</details>
|
|
691
|
+
|
|
692
|
+
**More:** See [CONTRIBUTING.md][contributing], [SECURITY.md][security], [tests/README.md](./tests/README.md)
|
|
693
|
+
|
|
694
|
+
## π§ͺ Testing
|
|
695
|
+
|
|
696
|
+
Comprehensive test suite included:
|
|
697
|
+
|
|
698
|
+
```bash
|
|
699
|
+
npm test # Run all tests
|
|
700
|
+
npm run test:unit # Unit tests only
|
|
701
|
+
npm run test:integration # Integration tests only
|
|
702
|
+
npm run test:e2e # End-to-end tests only
|
|
703
|
+
npm run test:e2e:real-llm # Real LLM integration tests (requires Ollama)
|
|
704
|
+
npm run test:coverage # Generate coverage report
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
See [tests/README.md](./tests/README.md) for details.
|
|
708
|
+
|
|
709
|
+
## π€ Contributing
|
|
710
|
+
|
|
711
|
+
Contributions welcome! See [CONTRIBUTING.md][contributing] for guidelines.
|
|
712
|
+
|
|
713
|
+
Quick start:
|
|
714
|
+
|
|
715
|
+
1. Fork the repository
|
|
716
|
+
2. Create your feature branch
|
|
717
|
+
3. Make your changes and test
|
|
718
|
+
4. Commit using [Conventional Commits](https://www.conventionalcommits.org/)
|
|
719
|
+
5. Open a Pull Request
|
|
720
|
+
|
|
721
|
+
Note: This project follows a [Code of Conduct][code-of-conduct].
|
|
722
|
+
|
|
723
|
+
## π Complementary Projects
|
|
724
|
+
|
|
725
|
+
**Maximize your MCP workflow with these complementary tools:**
|
|
726
|
+
|
|
727
|
+
### [Local Skills MCP][local-skills-mcp]
|
|
728
|
+
|
|
729
|
+
**Portable, reusable prompt libraries for any MCP client**
|
|
730
|
+
|
|
731
|
+
While MCP Compression Proxy optimizes your tool descriptions, [Local Skills MCP][local-skills-mcp] provides expert-level prompt instructions that work across any MCP-compatible client.
|
|
732
|
+
|
|
733
|
+
**Perfect combination:**
|
|
734
|
+
- **MCP Compression Proxy** - Aggregates and compresses tool descriptions (50-80% token reduction)
|
|
735
|
+
- **Local Skills MCP** - Provides expert skills with lazy loading (~50 tokens/skill)
|
|
736
|
+
|
|
737
|
+
**Together they enable:**
|
|
738
|
+
- π― Optimized context usage across tools AND prompts
|
|
739
|
+
- π Portable workflows that work with Claude, Cline, Continue.dev, and more
|
|
740
|
+
- β‘ Efficient AI interactions with minimal context consumption
|
|
741
|
+
- π Professional-grade AI agent capabilities
|
|
742
|
+
|
|
743
|
+
[Learn more about Local Skills MCP β][local-skills-mcp]
|
|
744
|
+
|
|
745
|
+
## π Support This Project
|
|
746
|
+
|
|
747
|
+
If you find MCP Compression Proxy useful, please consider supporting its development!
|
|
748
|
+
|
|
749
|
+
<div align="center">
|
|
750
|
+
|
|
751
|
+
[![GitHub Sponsors][sponsor-github-badge]][sponsor-github]
|
|
752
|
+
[![Buy Me A Coffee][sponsor-coffee-badge]][sponsor-coffee]
|
|
753
|
+
[![PayPal][sponsor-paypal-badge]][sponsor-paypal]
|
|
754
|
+
|
|
755
|
+
</div>
|
|
756
|
+
|
|
757
|
+
**Ways to support:**
|
|
758
|
+
|
|
759
|
+
- β [Star this repository][stargazers]
|
|
760
|
+
- π° Sponsor via the badges above
|
|
761
|
+
- π [Report bugs and suggest features][repo-issues]
|
|
762
|
+
- π [Contribute code or documentation][contributing]
|
|
763
|
+
|
|
764
|
+
## π License
|
|
765
|
+
|
|
766
|
+
MIT License - see [LICENSE][license-file] file. **Copyright Β© 2025 KDPA**
|
|
767
|
+
|
|
768
|
+
## π Acknowledgments
|
|
769
|
+
|
|
770
|
+
Built with [Model Context Protocol SDK][mcp-sdk]
|
|
771
|
+
|
|
772
|
+
---
|
|
773
|
+
|
|
774
|
+
<div align="center">
|
|
775
|
+
|
|
776
|
+
**[β¬ Back to Top](#-mcp-compression-proxy)**
|
|
777
|
+
|
|
778
|
+
Made with β€οΈ by KDPA
|
|
779
|
+
|
|
780
|
+
</div>
|
|
781
|
+
|
|
782
|
+
<!-- Reference Links -->
|
|
783
|
+
<!-- Badges - Top of README -->
|
|
784
|
+
|
|
785
|
+
[npm-version-badge]: https://img.shields.io/npm/v/mcp-compression-proxy.svg
|
|
786
|
+
[npm-package]: https://www.npmjs.com/package/mcp-compression-proxy
|
|
787
|
+
[npm-downloads-badge]: https://img.shields.io/npm/dm/mcp-compression-proxy
|
|
788
|
+
[npm-types-badge]: https://img.shields.io/npm/types/mcp-compression-proxy
|
|
789
|
+
[license-badge]: https://img.shields.io/badge/License-MIT-yellow.svg
|
|
790
|
+
[license]: https://opensource.org/licenses/MIT
|
|
791
|
+
[node-badge]: https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen.svg
|
|
792
|
+
[nodejs]: https://nodejs.org/
|
|
793
|
+
[mcp-badge]: https://img.shields.io/badge/MCP-Compatible-purple.svg
|
|
794
|
+
[mcp-protocol]: https://modelcontextprotocol.io/
|
|
795
|
+
[mcp-sampling]: https://modelcontextprotocol.io/docs/concepts/sampling
|
|
796
|
+
|
|
797
|
+
<!-- CI/CD Badges -->
|
|
798
|
+
|
|
799
|
+
[ci-badge]: https://github.com/kdpa-llc/mcp-compression-proxy/actions/workflows/test.yml/badge.svg
|
|
800
|
+
[ci-workflow]: https://github.com/kdpa-llc/mcp-compression-proxy/actions/workflows/test.yml
|
|
801
|
+
[codecov-badge]: https://codecov.io/gh/kdpa-llc/mcp-compression-proxy/branch/main/graph/badge.svg
|
|
802
|
+
[codecov]: https://codecov.io/gh/kdpa-llc/mcp-compression-proxy
|
|
803
|
+
[codeql-badge]: https://github.com/kdpa-llc/mcp-compression-proxy/actions/workflows/codeql.yml/badge.svg
|
|
804
|
+
[codeql-workflow]: https://github.com/kdpa-llc/mcp-compression-proxy/actions/workflows/codeql.yml
|
|
805
|
+
|
|
806
|
+
<!-- GitHub Badges -->
|
|
807
|
+
|
|
808
|
+
[stars-badge]: https://img.shields.io/github/stars/kdpa-llc/mcp-compression-proxy?style=social
|
|
809
|
+
[stargazers]: https://github.com/kdpa-llc/mcp-compression-proxy/stargazers
|
|
810
|
+
[forks-badge]: https://img.shields.io/github/forks/kdpa-llc/mcp-compression-proxy?style=social
|
|
811
|
+
[network]: https://github.com/kdpa-llc/mcp-compression-proxy/network/members
|
|
812
|
+
[issues-badge]: https://img.shields.io/github/issues/kdpa-llc/mcp-compression-proxy
|
|
813
|
+
[repo-issues]: https://github.com/kdpa-llc/mcp-compression-proxy/issues
|
|
814
|
+
[commit-badge]: https://img.shields.io/github/last-commit/kdpa-llc/mcp-compression-proxy
|
|
815
|
+
[commits]: https://github.com/kdpa-llc/mcp-compression-proxy/commits/main
|
|
816
|
+
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
|
|
817
|
+
|
|
818
|
+
<!-- Repository Links -->
|
|
819
|
+
|
|
820
|
+
[repo]: https://github.com/kdpa-llc/mcp-compression-proxy
|
|
821
|
+
[pulls]: https://github.com/kdpa-llc/mcp-compression-proxy/pulls
|
|
822
|
+
|
|
823
|
+
<!-- Documentation Links -->
|
|
824
|
+
|
|
825
|
+
[contributing]: CONTRIBUTING.md
|
|
826
|
+
[security]: SECURITY.md
|
|
827
|
+
[code-of-conduct]: CODE_OF_CONDUCT.md
|
|
828
|
+
[license-file]: LICENSE
|
|
829
|
+
|
|
830
|
+
<!-- Sponsorship Links -->
|
|
831
|
+
|
|
832
|
+
[sponsor-github-badge]: https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-ea4aaa?logo=github
|
|
833
|
+
[sponsor-github]: https://github.com/sponsors/moscaverd
|
|
834
|
+
[sponsor-coffee-badge]: https://img.shields.io/badge/Buy%20Me%20A%20Coffee-support-yellow?logo=buy-me-a-coffee
|
|
835
|
+
[sponsor-coffee]: https://buymeacoffee.com/moscaverd
|
|
836
|
+
[sponsor-paypal-badge]: https://img.shields.io/badge/PayPal-donate-blue?logo=paypal
|
|
837
|
+
[sponsor-paypal]: https://paypal.me/moscaverd
|
|
838
|
+
|
|
839
|
+
<!-- External Links -->
|
|
840
|
+
|
|
841
|
+
[mcp-sdk]: https://github.com/modelcontextprotocol/sdk
|
|
842
|
+
[local-skills-mcp]: https://github.com/kdpa-llc/local-skills-mcp
|