@mcp-bastion/core 1.0.8 → 1.0.11
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 +11 -12
- package/dist/guard.d.ts.map +1 -1
- package/dist/guard.test.d.ts +2 -0
- package/dist/guard.test.d.ts.map +1 -0
- package/dist/index.js +16 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @mcp-bastion/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[npm](https://www.npmjs.com/package/@mcp-bastion/core)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Security middleware for MCP servers. Rate limiting in-process; prompt injection and PII via optional sidecar.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -12,6 +12,8 @@ npm install @mcp-bastion/core @modelcontextprotocol/sdk
|
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
|
+
Set `MCP_BASTION_URL` to the sidecar URL (e.g. `http://localhost:8000`) to enable prompt guard and PII redaction. Omit it for rate limiting only.
|
|
16
|
+
|
|
15
17
|
```typescript
|
|
16
18
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
17
19
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -21,11 +23,8 @@ const server = new Server({ name: "my-mcp-server", version: "1.0.0" });
|
|
|
21
23
|
|
|
22
24
|
wrapWithMcpBastion(server, {
|
|
23
25
|
enableRateLimit: true,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
sidecarUrl: process.env.MCP_BASTION_SIDECAR || "",
|
|
27
|
-
enablePromptGuard: !!process.env.MCP_BASTION_SIDECAR,
|
|
28
|
-
enablePiiRedaction: !!process.env.MCP_BASTION_SIDECAR,
|
|
26
|
+
enablePromptGuard: true,
|
|
27
|
+
enablePiiRedaction: true,
|
|
29
28
|
});
|
|
30
29
|
|
|
31
30
|
server.setRequestHandler("tools/call" as any, async (request) => {
|
|
@@ -46,10 +45,10 @@ await server.connect(transport);
|
|
|
46
45
|
| enableRateLimit | true | Cap tool calls per session |
|
|
47
46
|
| maxIterations | 15 | Max tool calls before block |
|
|
48
47
|
| timeoutMs | 60000 | Session timeout |
|
|
49
|
-
| sidecarUrl |
|
|
50
|
-
| enablePromptGuard | false |
|
|
51
|
-
| enablePiiRedaction | false |
|
|
48
|
+
| sidecarUrl | (none) | Sidecar URL; falls back to MCP_BASTION_URL |
|
|
49
|
+
| enablePromptGuard | false | Needs sidecar (sidecarUrl or MCP_BASTION_URL) |
|
|
50
|
+
| enablePiiRedaction | false | Needs sidecar |
|
|
52
51
|
|
|
53
|
-
## Full
|
|
52
|
+
## Full docs
|
|
54
53
|
|
|
55
|
-
See [MCP-Bastion](https://github.com/vaquarkhan/MCP-Bastion) for Python package, examples, and
|
|
54
|
+
See [MCP-Bastion](https://github.com/vaquarkhan/MCP-Bastion) for Python package, examples, and documentation.
|
package/dist/guard.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,oCAAoC,CAAC;AAI5C,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,oCAAoC,CAAC;AAI5C,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AA0CD,KAAK,eAAe,GAAG,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAC7E,KAAK,mBAAmB,GAAG,CACzB,OAAO,EAAE,mBAAmB,KACzB,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEjC,+EAA+E;AAC/E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,iBAAsB,GAC9B,eAAe,CAkEjB;AAED,0EAA0E;AAC1E,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,GAAE,iBAAsB,GAC9B,mBAAmB,CAwBrB;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,iBAAiB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,EAC7G,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,iBAAsB,GAC9B,CAAC,CAyBH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.test.d.ts","sourceRoot":"","sources":["../src/guard.test.ts"],"names":[],"mappings":""}
|
package/dist/index.js
CHANGED
|
@@ -95,8 +95,14 @@ function createMcpError(code, message) {
|
|
|
95
95
|
isError: true
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
function getSidecarUrl(opts) {
|
|
99
|
+
if (opts.sidecarUrl) return opts.sidecarUrl;
|
|
100
|
+
if (typeof process !== "undefined" && process.env?.MCP_BASTION_URL)
|
|
101
|
+
return process.env.MCP_BASTION_URL;
|
|
102
|
+
return "";
|
|
103
|
+
}
|
|
104
|
+
async function callSidecar(baseUrl, endpoint, payload) {
|
|
105
|
+
const res = await fetch(`${baseUrl}/${endpoint}`, {
|
|
100
106
|
method: "POST",
|
|
101
107
|
headers: { "Content-Type": "application/json" },
|
|
102
108
|
body: JSON.stringify(payload)
|
|
@@ -108,6 +114,7 @@ async function callSidecar(url, endpoint, payload) {
|
|
|
108
114
|
}
|
|
109
115
|
function wrapCallToolHandler(handler, options = {}) {
|
|
110
116
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
117
|
+
const sidecarUrl = getSidecarUrl(opts);
|
|
111
118
|
const rateLimiter = new TokenBucketRateLimiter(
|
|
112
119
|
opts.maxIterations,
|
|
113
120
|
opts.timeoutMs
|
|
@@ -125,12 +132,12 @@ function wrapCallToolHandler(handler, options = {}) {
|
|
|
125
132
|
return createMcpError(-32002, error ?? "Rate limit exceeded");
|
|
126
133
|
}
|
|
127
134
|
}
|
|
128
|
-
if (opts.enablePromptGuard &&
|
|
135
|
+
if (opts.enablePromptGuard && sidecarUrl) {
|
|
129
136
|
try {
|
|
130
137
|
const args = request.params?.arguments ?? {};
|
|
131
138
|
const text = JSON.stringify(args);
|
|
132
139
|
const result2 = await callSidecar(
|
|
133
|
-
|
|
140
|
+
sidecarUrl,
|
|
134
141
|
"prompt-guard",
|
|
135
142
|
{ text }
|
|
136
143
|
);
|
|
@@ -148,10 +155,10 @@ function wrapCallToolHandler(handler, options = {}) {
|
|
|
148
155
|
}
|
|
149
156
|
rateLimiter.consumeIteration(requestId, sessionId);
|
|
150
157
|
let result = await handler(request);
|
|
151
|
-
if (opts.enablePiiRedaction &&
|
|
158
|
+
if (opts.enablePiiRedaction && sidecarUrl && result?.content) {
|
|
152
159
|
try {
|
|
153
160
|
const redacted = await callSidecar(
|
|
154
|
-
|
|
161
|
+
sidecarUrl,
|
|
155
162
|
"pii-redact",
|
|
156
163
|
{ content: result.content }
|
|
157
164
|
);
|
|
@@ -167,12 +174,13 @@ function wrapCallToolHandler(handler, options = {}) {
|
|
|
167
174
|
}
|
|
168
175
|
function wrapReadResourceHandler(handler, options = {}) {
|
|
169
176
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
177
|
+
const sidecarUrl = getSidecarUrl(opts);
|
|
170
178
|
return async (request) => {
|
|
171
179
|
const result = await handler(request);
|
|
172
|
-
if (opts.enablePiiRedaction &&
|
|
180
|
+
if (opts.enablePiiRedaction && sidecarUrl && result?.contents) {
|
|
173
181
|
try {
|
|
174
182
|
const redacted = await callSidecar(
|
|
175
|
-
|
|
183
|
+
sidecarUrl,
|
|
176
184
|
"pii-redact",
|
|
177
185
|
{ content: result.contents }
|
|
178
186
|
);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/rate-limit.ts","../src/logger.ts","../src/guard.ts"],"sourcesContent":["/**\n * Token bucket rate limiter for MCP tool calls.\n * Iteration cap (15), timeout (60s).\n */\n\nconst DEFAULT_MAX_ITERATIONS = 15;\nconst DEFAULT_TIMEOUT_MS = 60_000;\n\ninterface SessionState {\n iterations: number;\n startedAt: number;\n}\n\nexport class TokenBucketRateLimiter {\n private readonly maxIterations: number;\n private readonly timeoutMs: number;\n private readonly sessions = new Map<string, SessionState>();\n\n constructor(\n maxIterations = DEFAULT_MAX_ITERATIONS,\n timeoutMs = DEFAULT_TIMEOUT_MS\n ) {\n this.maxIterations = maxIterations;\n this.timeoutMs = timeoutMs;\n }\n\n private getSessionKey(requestId?: string | null, sessionId?: string | null): string {\n return sessionId ?? requestId ?? \"default\";\n }\n\n private cleanupExpired(key: string): void {\n const state = this.sessions.get(key);\n if (!state) return;\n const elapsed = Date.now() - state.startedAt;\n if (elapsed > this.timeoutMs) {\n this.sessions.delete(key);\n }\n }\n\n checkIteration(\n requestId?: string | null,\n sessionId?: string | null\n ): { allowed: boolean; error?: string } {\n const key = this.getSessionKey(requestId, sessionId);\n this.cleanupExpired(key);\n\n const state = this.sessions.get(key);\n if (!state) {\n return { allowed: true };\n }\n\n const elapsed = Date.now() - state.startedAt;\n if (elapsed > this.timeoutMs) {\n this.sessions.delete(key);\n return { allowed: false, error: \"Session timeout exceeded (60s limit)\" };\n }\n\n if (state.iterations >= this.maxIterations) {\n return {\n allowed: false,\n error: `Maximum iterations exceeded (${this.maxIterations} limit)`,\n };\n }\n\n return { allowed: true };\n }\n\n consumeIteration(\n requestId?: string | null,\n sessionId?: string | null\n ): void {\n const key = this.getSessionKey(requestId, sessionId);\n let state = this.sessions.get(key);\n if (!state) {\n state = { iterations: 0, startedAt: Date.now() };\n this.sessions.set(key, state);\n }\n state.iterations += 1;\n }\n\n resetSession(requestId?: string | null, sessionId?: string | null): void {\n const key = this.getSessionKey(requestId, sessionId);\n this.sessions.delete(key);\n }\n}\n","/**\n * Simple logger for MCP-Bastion. Uses console with level filtering.\n */\n\nconst PREFIX = \"[mcp-bastion]\";\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet currentLevel: LogLevel = \"info\";\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[currentLevel];\n}\n\nexport const logger = {\n debug(msg: string, ...args: unknown[]): void {\n if (shouldLog(\"debug\")) console.debug(PREFIX, msg, ...args);\n },\n info(msg: string, ...args: unknown[]): void {\n if (shouldLog(\"info\")) console.info(PREFIX, msg, ...args);\n },\n warn(msg: string, ...args: unknown[]): void {\n if (shouldLog(\"warn\")) console.warn(PREFIX, msg, ...args);\n },\n error(msg: string, ...args: unknown[]): void {\n if (shouldLog(\"error\")) console.error(PREFIX, msg, ...args);\n },\n};\n","/**\n * MCP-Bastion proxy wrapper for MCP server handlers.\n * Wraps CallTool and ReadResource; rate limit in-process, ML via sidecar.\n */\n\nimport type {\n CallToolRequest,\n CallToolResult,\n ReadResourceRequest,\n ReadResourceResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { TokenBucketRateLimiter } from \"./rate-limit.js\";\nimport { logger } from \"./logger.js\";\n\nexport interface McpBastionOptions {\n maxIterations?: number;\n timeoutMs?: number;\n enableRateLimit?: boolean;\n sidecarUrl?: string;\n enablePromptGuard?: boolean;\n enablePiiRedaction?: boolean;\n}\n\nconst DEFAULT_OPTIONS: Required<McpBastionOptions> = {\n maxIterations: 15,\n timeoutMs: 60_000,\n enableRateLimit: true,\n sidecarUrl: \"\",\n enablePromptGuard: false,\n enablePiiRedaction: false,\n};\n\nfunction createMcpError(code: number, message: string): CallToolResult {\n return {\n content: [{ type: \"text\", text: `[MCP-Bastion] ${message}` }],\n isError: true,\n };\n}\n\nasync function callSidecar(\n url: string,\n endpoint: \"prompt-guard\" | \"pii-redact\",\n payload: unknown\n): Promise<unknown> {\n const res = await fetch(`${url}/${endpoint}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n if (!res.ok) {\n throw new Error(`Sidecar ${endpoint} failed: ${res.status}`);\n }\n return res.json();\n}\n\ntype CallToolHandler = (request: CallToolRequest) => Promise<CallToolResult>;\ntype ReadResourceHandler = (\n request: ReadResourceRequest\n) => Promise<ReadResourceResult>;\n\n/** Wraps CallTool handler. Rate limit in-process; prompt guard via sidecar. */\nexport function wrapCallToolHandler(\n handler: CallToolHandler,\n options: McpBastionOptions = {}\n): CallToolHandler {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const rateLimiter = new TokenBucketRateLimiter(\n opts.maxIterations,\n opts.timeoutMs\n );\n\n return async (request: CallToolRequest): Promise<CallToolResult> => {\n const requestId = String((request as { id?: string | number }).id ?? \"\");\n const sessionId = (request.params?._meta as Record<string, string>)?.[\"session_id\"];\n\n if (opts.enableRateLimit) {\n const { allowed, error } = rateLimiter.checkIteration(\n requestId,\n sessionId\n );\n if (!allowed) {\n logger.warn(\"rate_limit_blocked\", requestId, sessionId, error);\n return createMcpError(-32002, error ?? \"Rate limit exceeded\");\n }\n }\n\n if (opts.enablePromptGuard && opts.sidecarUrl) {\n try {\n const args = request.params?.arguments ?? {};\n const text = JSON.stringify(args);\n const result = (await callSidecar(\n opts.sidecarUrl,\n \"prompt-guard\",\n { text }\n )) as { malicious?: boolean };\n if (result?.malicious) {\n logger.warn(\"prompt_injection_blocked\", requestId);\n return createMcpError(\n -32001,\n \"Request blocked: potential prompt injection detected\"\n );\n }\n } catch (err) {\n logger.warn(\"prompt_guard_sidecar_unavailable\", err);\n return createMcpError(-32001, \"Prompt guard sidecar unavailable\");\n }\n }\n\n rateLimiter.consumeIteration(requestId, sessionId);\n\n let result = await handler(request);\n\n if (opts.enablePiiRedaction && opts.sidecarUrl && result?.content) {\n try {\n const redacted = (await callSidecar(\n opts.sidecarUrl,\n \"pii-redact\",\n { content: result.content }\n )) as { content?: CallToolResult[\"content\"] };\n if (redacted?.content) {\n result = { ...result, content: redacted.content };\n }\n } catch {\n return result;\n }\n }\n\n return result;\n };\n}\n\n/** Wraps ReadResource handler. PII redaction via sidecar when enabled. */\nexport function wrapReadResourceHandler(\n handler: ReadResourceHandler,\n options: McpBastionOptions = {}\n): ReadResourceHandler {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n return async (request: ReadResourceRequest): Promise<ReadResourceResult> => {\n const result = await handler(request);\n\n if (opts.enablePiiRedaction && opts.sidecarUrl && result?.contents) {\n try {\n const redacted = (await callSidecar(\n opts.sidecarUrl,\n \"pii-redact\",\n { content: result.contents }\n )) as { content?: ReadResourceResult[\"contents\"] };\n if (redacted?.content) {\n return { ...result, contents: redacted.content };\n }\n } catch {\n return result;\n }\n }\n\n return result;\n };\n}\n\n/** Patches setRequestHandler to wrap CallTool and ReadResource handlers. */\nexport function wrapWithMcpBastion<T extends { setRequestHandler: (schema: unknown, handler: unknown) => void }>(\n server: T,\n options: McpBastionOptions = {}\n): T {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const original = server.setRequestHandler.bind(server);\n\n server.setRequestHandler = function (\n schema: unknown,\n handler: unknown\n ): void {\n const schemaStr = String((schema as { name?: string })?.name ?? schema);\n if (schemaStr.includes(\"CallTool\") || schemaStr.includes(\"tools/call\")) {\n return original(\n schema,\n wrapCallToolHandler(handler as CallToolHandler, opts)\n );\n }\n if (schemaStr.includes(\"ReadResource\") || schemaStr.includes(\"resources/read\")) {\n return original(\n schema,\n wrapReadResourceHandler(handler as ReadResourceHandler, opts)\n );\n }\n return original(schema, handler);\n } as T[\"setRequestHandler\"];\n\n return server;\n}\n"],"names":["result"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/rate-limit.ts","../src/logger.ts","../src/guard.ts"],"sourcesContent":["/**\n * Token bucket rate limiter for MCP tool calls.\n * Iteration cap (15), timeout (60s).\n */\n\nconst DEFAULT_MAX_ITERATIONS = 15;\nconst DEFAULT_TIMEOUT_MS = 60_000;\n\ninterface SessionState {\n iterations: number;\n startedAt: number;\n}\n\nexport class TokenBucketRateLimiter {\n private readonly maxIterations: number;\n private readonly timeoutMs: number;\n private readonly sessions = new Map<string, SessionState>();\n\n constructor(\n maxIterations = DEFAULT_MAX_ITERATIONS,\n timeoutMs = DEFAULT_TIMEOUT_MS\n ) {\n this.maxIterations = maxIterations;\n this.timeoutMs = timeoutMs;\n }\n\n private getSessionKey(requestId?: string | null, sessionId?: string | null): string {\n return sessionId ?? requestId ?? \"default\";\n }\n\n private cleanupExpired(key: string): void {\n const state = this.sessions.get(key);\n if (!state) return;\n const elapsed = Date.now() - state.startedAt;\n if (elapsed > this.timeoutMs) {\n this.sessions.delete(key);\n }\n }\n\n checkIteration(\n requestId?: string | null,\n sessionId?: string | null\n ): { allowed: boolean; error?: string } {\n const key = this.getSessionKey(requestId, sessionId);\n this.cleanupExpired(key);\n\n const state = this.sessions.get(key);\n if (!state) {\n return { allowed: true };\n }\n\n const elapsed = Date.now() - state.startedAt;\n if (elapsed > this.timeoutMs) {\n this.sessions.delete(key);\n return { allowed: false, error: \"Session timeout exceeded (60s limit)\" };\n }\n\n if (state.iterations >= this.maxIterations) {\n return {\n allowed: false,\n error: `Maximum iterations exceeded (${this.maxIterations} limit)`,\n };\n }\n\n return { allowed: true };\n }\n\n consumeIteration(\n requestId?: string | null,\n sessionId?: string | null\n ): void {\n const key = this.getSessionKey(requestId, sessionId);\n let state = this.sessions.get(key);\n if (!state) {\n state = { iterations: 0, startedAt: Date.now() };\n this.sessions.set(key, state);\n }\n state.iterations += 1;\n }\n\n resetSession(requestId?: string | null, sessionId?: string | null): void {\n const key = this.getSessionKey(requestId, sessionId);\n this.sessions.delete(key);\n }\n}\n","/**\n * Simple logger for MCP-Bastion. Uses console with level filtering.\n */\n\nconst PREFIX = \"[mcp-bastion]\";\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet currentLevel: LogLevel = \"info\";\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LEVEL_ORDER[level] >= LEVEL_ORDER[currentLevel];\n}\n\nexport const logger = {\n debug(msg: string, ...args: unknown[]): void {\n if (shouldLog(\"debug\")) console.debug(PREFIX, msg, ...args);\n },\n info(msg: string, ...args: unknown[]): void {\n if (shouldLog(\"info\")) console.info(PREFIX, msg, ...args);\n },\n warn(msg: string, ...args: unknown[]): void {\n if (shouldLog(\"warn\")) console.warn(PREFIX, msg, ...args);\n },\n error(msg: string, ...args: unknown[]): void {\n if (shouldLog(\"error\")) console.error(PREFIX, msg, ...args);\n },\n};\n","/**\n * MCP-Bastion proxy wrapper for MCP server handlers.\n * Wraps CallTool and ReadResource; rate limit in-process, ML via sidecar.\n */\n\nimport type {\n CallToolRequest,\n CallToolResult,\n ReadResourceRequest,\n ReadResourceResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { TokenBucketRateLimiter } from \"./rate-limit.js\";\nimport { logger } from \"./logger.js\";\n\nexport interface McpBastionOptions {\n maxIterations?: number;\n timeoutMs?: number;\n enableRateLimit?: boolean;\n sidecarUrl?: string;\n enablePromptGuard?: boolean;\n enablePiiRedaction?: boolean;\n}\n\nconst DEFAULT_OPTIONS: Required<McpBastionOptions> = {\n maxIterations: 15,\n timeoutMs: 60_000,\n enableRateLimit: true,\n sidecarUrl: \"\",\n enablePromptGuard: false,\n enablePiiRedaction: false,\n};\n\nfunction createMcpError(code: number, message: string): CallToolResult {\n return {\n content: [{ type: \"text\", text: `[MCP-Bastion] ${message}` }],\n isError: true,\n };\n}\n\n/** Resolve sidecar base URL from options or env MCP_BASTION_URL. */\nfunction getSidecarUrl(opts: Required<McpBastionOptions>): string {\n if (opts.sidecarUrl) return opts.sidecarUrl;\n if (typeof process !== \"undefined\" && process.env?.MCP_BASTION_URL)\n return process.env.MCP_BASTION_URL;\n return \"\";\n}\n\nasync function callSidecar(\n baseUrl: string,\n endpoint: \"prompt-guard\" | \"pii-redact\",\n payload: unknown\n): Promise<unknown> {\n const res = await fetch(`${baseUrl}/${endpoint}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n if (!res.ok) {\n throw new Error(`Sidecar ${endpoint} failed: ${res.status}`);\n }\n return res.json();\n}\n\ntype CallToolHandler = (request: CallToolRequest) => Promise<CallToolResult>;\ntype ReadResourceHandler = (\n request: ReadResourceRequest\n) => Promise<ReadResourceResult>;\n\n/** Wraps CallTool handler. Rate limit in-process; prompt guard via sidecar. */\nexport function wrapCallToolHandler(\n handler: CallToolHandler,\n options: McpBastionOptions = {}\n): CallToolHandler {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const sidecarUrl = getSidecarUrl(opts);\n const rateLimiter = new TokenBucketRateLimiter(\n opts.maxIterations,\n opts.timeoutMs\n );\n\n return async (request: CallToolRequest): Promise<CallToolResult> => {\n const requestId = String((request as { id?: string | number }).id ?? \"\");\n const sessionId = (request.params?._meta as Record<string, string>)?.[\"session_id\"];\n\n if (opts.enableRateLimit) {\n const { allowed, error } = rateLimiter.checkIteration(\n requestId,\n sessionId\n );\n if (!allowed) {\n logger.warn(\"rate_limit_blocked\", requestId, sessionId, error);\n return createMcpError(-32002, error ?? \"Rate limit exceeded\");\n }\n }\n\n if (opts.enablePromptGuard && sidecarUrl) {\n try {\n const args = request.params?.arguments ?? {};\n const text = JSON.stringify(args);\n const result = (await callSidecar(\n sidecarUrl,\n \"prompt-guard\",\n { text }\n )) as { malicious?: boolean };\n if (result?.malicious) {\n logger.warn(\"prompt_injection_blocked\", requestId);\n return createMcpError(\n -32001,\n \"Request blocked: potential prompt injection detected\"\n );\n }\n } catch (err) {\n logger.warn(\"prompt_guard_sidecar_unavailable\", err);\n return createMcpError(-32001, \"Prompt guard sidecar unavailable\");\n }\n }\n\n rateLimiter.consumeIteration(requestId, sessionId);\n\n let result = await handler(request);\n\n if (opts.enablePiiRedaction && sidecarUrl && result?.content) {\n try {\n const redacted = (await callSidecar(\n sidecarUrl,\n \"pii-redact\",\n { content: result.content }\n )) as { content?: CallToolResult[\"content\"] };\n if (redacted?.content) {\n result = { ...result, content: redacted.content };\n }\n } catch {\n return result;\n }\n }\n\n return result;\n };\n}\n\n/** Wraps ReadResource handler. PII redaction via sidecar when enabled. */\nexport function wrapReadResourceHandler(\n handler: ReadResourceHandler,\n options: McpBastionOptions = {}\n): ReadResourceHandler {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const sidecarUrl = getSidecarUrl(opts);\n\n return async (request: ReadResourceRequest): Promise<ReadResourceResult> => {\n const result = await handler(request);\n\n if (opts.enablePiiRedaction && sidecarUrl && result?.contents) {\n try {\n const redacted = (await callSidecar(\n sidecarUrl,\n \"pii-redact\",\n { content: result.contents }\n )) as { content?: ReadResourceResult[\"contents\"] };\n if (redacted?.content) {\n return { ...result, contents: redacted.content };\n }\n } catch {\n return result;\n }\n }\n\n return result;\n };\n}\n\n/** Patches setRequestHandler to wrap CallTool and ReadResource handlers. */\nexport function wrapWithMcpBastion<T extends { setRequestHandler: (schema: unknown, handler: unknown) => void }>(\n server: T,\n options: McpBastionOptions = {}\n): T {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const original = server.setRequestHandler.bind(server);\n\n server.setRequestHandler = function (\n schema: unknown,\n handler: unknown\n ): void {\n const schemaStr = String((schema as { name?: string })?.name ?? schema);\n if (schemaStr.includes(\"CallTool\") || schemaStr.includes(\"tools/call\")) {\n return original(\n schema,\n wrapCallToolHandler(handler as CallToolHandler, opts)\n );\n }\n if (schemaStr.includes(\"ReadResource\") || schemaStr.includes(\"resources/read\")) {\n return original(\n schema,\n wrapReadResourceHandler(handler as ReadResourceHandler, opts)\n );\n }\n return original(schema, handler);\n } as T[\"setRequestHandler\"];\n\n return server;\n}\n"],"names":["result"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-bastion/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"mcpName": "io.github.vaquarkhan/mcp-bastion",
|
|
5
5
|
"description": "Security middleware for MCP servers protecting LLM agents from prompt injection, resource exhaustion, and PII leakage",
|
|
6
6
|
"type": "module",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
+
"@types/node": "^20.0.0",
|
|
45
46
|
"typescript": "^5.3.0",
|
|
46
47
|
"vite": "^5.0.0",
|
|
47
48
|
"vitest": "^1.0.0"
|