@aiwerk/mcp-bridge 1.2.3 → 1.3.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 +32 -1
- package/dist/src/mcp-router.d.ts +6 -0
- package/dist/src/mcp-router.js +29 -2
- package/dist/src/schema-compression.d.ts +4 -0
- package/dist/src/schema-compression.js +21 -0
- package/dist/src/types.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -115,10 +115,38 @@ Config: `~/.mcp-bridge/config.json` | Secrets: `~/.mcp-bridge/.env`
|
|
|
115
115
|
},
|
|
116
116
|
"toolPrefix": true,
|
|
117
117
|
"connectionTimeoutMs": 5000,
|
|
118
|
-
"requestTimeoutMs": 60000
|
|
118
|
+
"requestTimeoutMs": 60000,
|
|
119
|
+
"schemaCompression": {
|
|
120
|
+
"enabled": true,
|
|
121
|
+
"maxDescriptionLength": 80
|
|
122
|
+
}
|
|
119
123
|
}
|
|
120
124
|
```
|
|
121
125
|
|
|
126
|
+
### Schema Compression
|
|
127
|
+
|
|
128
|
+
In router mode, tool descriptions from upstream servers can be verbose (100-300+ chars each). Schema compression truncates them to save tokens:
|
|
129
|
+
|
|
130
|
+
- **Enabled by default** — descriptions capped at 80 characters
|
|
131
|
+
- Cuts at sentence boundary when possible, otherwise word boundary
|
|
132
|
+
- Use `action=schema` to retrieve the full uncompressed schema for any tool on demand
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
"schemaCompression": {
|
|
136
|
+
"enabled": true,
|
|
137
|
+
"maxDescriptionLength": 80
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Token savings example:** 30 Todoist tools: ~2800 tokens uncompressed -> ~1200 compressed (~57% reduction).
|
|
142
|
+
|
|
143
|
+
To get full details for a specific tool:
|
|
144
|
+
```
|
|
145
|
+
mcp(server="todoist", action="schema", tool="find-tasks")
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Set `"enabled": false` to disable compression and return full descriptions.
|
|
149
|
+
|
|
122
150
|
### Modes
|
|
123
151
|
|
|
124
152
|
| Mode | Tools exposed | Best for |
|
|
@@ -186,6 +214,9 @@ Built-in catalog with pre-configured servers:
|
|
|
186
214
|
| wise | stdio | International payments |
|
|
187
215
|
| tavily | stdio | AI-optimized web search |
|
|
188
216
|
| apify | streamable-http | Web scraping and automation |
|
|
217
|
+
| atlassian | stdio | Confluence and Jira |
|
|
218
|
+
| chrome-devtools | stdio | Chrome browser automation |
|
|
219
|
+
| hostinger | sse | Web hosting management |
|
|
189
220
|
|
|
190
221
|
```bash
|
|
191
222
|
mcp-bridge install todoist # Interactive setup with API key prompt
|
package/dist/src/mcp-router.d.ts
CHANGED
|
@@ -26,6 +26,12 @@ export type RouterDispatchResponse = {
|
|
|
26
26
|
action: "call";
|
|
27
27
|
tool: string;
|
|
28
28
|
result: any;
|
|
29
|
+
} | {
|
|
30
|
+
server: string;
|
|
31
|
+
action: "schema";
|
|
32
|
+
tool: string;
|
|
33
|
+
schema: any;
|
|
34
|
+
description: string;
|
|
29
35
|
} | {
|
|
30
36
|
action: "status";
|
|
31
37
|
servers: RouterServerStatus[];
|
package/dist/src/mcp-router.js
CHANGED
|
@@ -2,6 +2,7 @@ import { SseTransport } from "./transport-sse.js";
|
|
|
2
2
|
import { StdioTransport } from "./transport-stdio.js";
|
|
3
3
|
import { StreamableHttpTransport } from "./transport-streamable-http.js";
|
|
4
4
|
import { fetchToolsList, initializeProtocol, PACKAGE_VERSION } from "./protocol.js";
|
|
5
|
+
import { compressDescription } from "./schema-compression.js";
|
|
5
6
|
const DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
|
|
6
7
|
const DEFAULT_MAX_CONCURRENT = 5;
|
|
7
8
|
export class McpRouter {
|
|
@@ -59,10 +60,28 @@ export class McpRouter {
|
|
|
59
60
|
return this.error("connection_failed", `Failed to connect to ${server}: ${error instanceof Error ? error.message : String(error)}`);
|
|
60
61
|
}
|
|
61
62
|
}
|
|
63
|
+
if (normalizedAction === "schema") {
|
|
64
|
+
if (!tool) {
|
|
65
|
+
return this.error("invalid_params", "tool is required for action=schema");
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
await this.getToolList(server);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return this.error("connection_failed", `Failed to connect to ${server}: ${error instanceof Error ? error.message : String(error)}`);
|
|
72
|
+
}
|
|
73
|
+
const state = this.states.get(server);
|
|
74
|
+
const fullTool = state.fullToolsMap?.get(tool);
|
|
75
|
+
if (!fullTool) {
|
|
76
|
+
return this.error("unknown_tool", `Tool '${tool}' not found on server '${server}'`, state.toolNames);
|
|
77
|
+
}
|
|
78
|
+
return { server, action: "schema", tool, schema: fullTool.inputSchema, description: fullTool.description };
|
|
79
|
+
}
|
|
62
80
|
if (normalizedAction === "refresh") {
|
|
63
81
|
try {
|
|
64
82
|
const state = await this.ensureConnected(server);
|
|
65
83
|
state.toolsCache = undefined;
|
|
84
|
+
state.fullToolsMap = undefined;
|
|
66
85
|
state.toolNames = [];
|
|
67
86
|
const tools = await this.getToolList(server);
|
|
68
87
|
return { server, action: "refresh", refreshed: true, tools };
|
|
@@ -72,7 +91,7 @@ export class McpRouter {
|
|
|
72
91
|
}
|
|
73
92
|
}
|
|
74
93
|
if (normalizedAction !== "call") {
|
|
75
|
-
return this.error("invalid_params", `action must be one of: list, call, refresh`);
|
|
94
|
+
return this.error("invalid_params", `action must be one of: list, call, refresh, schema`);
|
|
76
95
|
}
|
|
77
96
|
if (!tool) {
|
|
78
97
|
return this.error("invalid_params", "tool is required for action=call");
|
|
@@ -116,9 +135,15 @@ export class McpRouter {
|
|
|
116
135
|
}
|
|
117
136
|
const tools = await fetchToolsList(state.transport);
|
|
118
137
|
state.toolNames = tools.map((tool) => tool.name);
|
|
138
|
+
// Store full tool metadata for action=schema
|
|
139
|
+
state.fullToolsMap = new Map(tools.map((tool) => [tool.name, { description: tool.description || "", inputSchema: tool.inputSchema }]));
|
|
140
|
+
const compressionEnabled = this.clientConfig.schemaCompression?.enabled ?? true;
|
|
141
|
+
const maxLen = this.clientConfig.schemaCompression?.maxDescriptionLength ?? 80;
|
|
119
142
|
state.toolsCache = tools.map((tool) => ({
|
|
120
143
|
name: tool.name,
|
|
121
|
-
description:
|
|
144
|
+
description: compressionEnabled
|
|
145
|
+
? compressDescription(tool.description || "", maxLen)
|
|
146
|
+
: (tool.description || ""),
|
|
122
147
|
requiredParams: this.extractRequiredParams(tool)
|
|
123
148
|
}));
|
|
124
149
|
this.markUsed(server);
|
|
@@ -213,6 +238,7 @@ export class McpRouter {
|
|
|
213
238
|
}
|
|
214
239
|
state.initialized = false;
|
|
215
240
|
state.toolsCache = undefined;
|
|
241
|
+
state.fullToolsMap = undefined;
|
|
216
242
|
state.toolNames = [];
|
|
217
243
|
}
|
|
218
244
|
markUsed(server) {
|
|
@@ -240,6 +266,7 @@ export class McpRouter {
|
|
|
240
266
|
return;
|
|
241
267
|
state.initialized = false;
|
|
242
268
|
state.toolsCache = undefined;
|
|
269
|
+
state.fullToolsMap = undefined;
|
|
243
270
|
state.toolNames = [];
|
|
244
271
|
};
|
|
245
272
|
if (serverConfig.transport === "sse") {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compress tool descriptions to reduce token usage in router tool listings.
|
|
3
|
+
*/
|
|
4
|
+
export function compressDescription(desc, maxLen = 80) {
|
|
5
|
+
if (desc.length <= maxLen) {
|
|
6
|
+
return desc;
|
|
7
|
+
}
|
|
8
|
+
// Try to cut at sentence boundary (". " before maxLen)
|
|
9
|
+
const searchArea = desc.slice(0, maxLen);
|
|
10
|
+
const sentenceEnd = searchArea.lastIndexOf(". ");
|
|
11
|
+
if (sentenceEnd > 0) {
|
|
12
|
+
return desc.slice(0, sentenceEnd + 1) + "\u2026";
|
|
13
|
+
}
|
|
14
|
+
// Fall back to word boundary
|
|
15
|
+
const lastSpace = searchArea.lastIndexOf(" ");
|
|
16
|
+
if (lastSpace > 0) {
|
|
17
|
+
return desc.slice(0, lastSpace) + "\u2026";
|
|
18
|
+
}
|
|
19
|
+
// No word boundary found, hard truncate
|
|
20
|
+
return desc.slice(0, maxLen) + "\u2026";
|
|
21
|
+
}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -24,6 +24,10 @@ export interface McpClientConfig {
|
|
|
24
24
|
requestTimeoutMs?: number;
|
|
25
25
|
routerIdleTimeoutMs?: number;
|
|
26
26
|
routerMaxConcurrent?: number;
|
|
27
|
+
schemaCompression?: {
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
maxDescriptionLength?: number;
|
|
30
|
+
};
|
|
27
31
|
}
|
|
28
32
|
export interface McpTool {
|
|
29
33
|
name: string;
|