@mcp-bastion/core 1.0.10 → 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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # @mcp-bastion/core
2
2
 
3
- Security middleware for MCP (Model Context Protocol) servers. Rate limiting in-process; prompt injection and PII via Python sidecar.
3
+ [npm](https://www.npmjs.com/package/@mcp-bastion/core)
4
4
 
5
- Author: Viquar Khan
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
- maxIterations: 15,
25
- timeoutMs: 60_000,
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 | "" | Python sidecar URL for ML features |
50
- | enablePromptGuard | false | Requires sidecarUrl |
51
- | enablePiiRedaction | false | Requires sidecarUrl |
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 Docs
52
+ ## Full docs
54
53
 
55
- See [MCP-Bastion](https://github.com/vaquarkhan/MCP-Bastion) for Python package, examples, and full documentation.
54
+ See [MCP-Bastion](https://github.com/vaquarkhan/MCP-Bastion) for Python package, examples, and documentation.
@@ -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;AAkCD,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,CAiEjB;AAED,0EAA0E;AAC1E,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,GAAE,iBAAsB,GAC9B,mBAAmB,CAuBrB;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"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=guard.test.d.ts.map
@@ -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
- async function callSidecar(url, endpoint, payload) {
99
- const res = await fetch(`${url}/${endpoint}`, {
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 && opts.sidecarUrl) {
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
- opts.sidecarUrl,
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 && opts.sidecarUrl && result?.content) {
158
+ if (opts.enablePiiRedaction && sidecarUrl && result?.content) {
152
159
  try {
153
160
  const redacted = await callSidecar(
154
- opts.sidecarUrl,
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 && opts.sidecarUrl && result?.contents) {
180
+ if (opts.enablePiiRedaction && sidecarUrl && result?.contents) {
173
181
  try {
174
182
  const redacted = await callSidecar(
175
- opts.sidecarUrl,
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.10",
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"