PII代理中间件

elastic-pii-proxy是一个透明的MCP代理中间件,位于LLM代理和上游MCP服务器之间,用于拦截工具调用和资源读取,在结果到达模型之前对PII进行脱敏,并生成符合GDPR的审计跟踪。

  • by amir-gorji
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 amir-gorji/elastic-pii-proxy

使用说明

弹性pii代理

A. 透明MCP代理 它位于LLM代理和上游MCP服务器(Elastic v8.18+或任何其他)之间。拦截工具调用和资源读取,在结果到达模型之前编辑PII,并发出GDPR正确的审计跟踪——原始PII永远不会触及审计日志。

构建为可组合的中间件堆栈:每个关注点(PII编辑、审计日志、合规性配置文件)都是一个可插拔的块。代理核心是通用的,可用于任何上游MCP服务器。


目录

  1. 建筑
  2. 快速开始
  3. 环境变量
  4. 合规性档案
  5. 中间件执行顺序
  6. 添加中间件
  7. 安全与合规
  8. 测试
  9. 项目结构
  10. 许可证

1.建筑

┌─────────────┐  MCP (stdio)  ┌────────────────────────────────────────┐  MCP (stdio)  ┌──────────────────┐
│  LLM Agent  │ ◄────────────► │           elastic-pii-proxy            │ ◄────────────► │  Elastic MCP     │
│  (Claude)   │               │                                        │               │  (v8.18+)        │
└─────────────┘               │  compose([auditMW, piiMW])             │               └──────────────────┘
                              │                                        │
                              │  ┌──────────────────────────────────┐  │
                              │  │  auditMiddleware  (outer layer)  │  │
                              │  │  ┌──────────────────────────┐    │  │
                              │  │  │  piiMiddleware  (inner)  │    │  │
                              │  │  │   ┌──────────────────┐   │    │  │
                              │  │  │   │  upstream call   │   │    │  │
                              │  │  │   └──────────────────┘   │    │  │
                              │  │  │  ↑ redact response here  │    │  │
                              │  │  └──────────────────────────┘    │  │
                              │  │  ↑ log AFTER redaction (safe)    │  │
                              │  └──────────────────────────────────┘  │
                              └────────────────────────────────────────┘

执行顺序 随着 compose([auditMW, piiMW]):

步骤 层 动作
1 审核MW输入 捕获 startTime
2 piiMW输入 呼叫上游
3 -- 上游Elastic MCP返回原始数据
4 piiMW退出 从响应中删除PII
5 auditMW退出 日志 清洁 结果+计时(从不记录原始PII)

2.快速入门

先决条件

  • Node.js 18+
  • 启用本地MCP服务器(或任何其他MCP服务器)的Elasticsearch v8.18+

安装和构建

git clone <this-repo>
cd elastic-pii-proxy
npm install
npm run build:mcp

配置(stdio上游)

export UPSTREAM_MCP_COMMAND="node"
export UPSTREAM_MCP_ARGS="/path/to/elastic-mcp/index.mjs"
export COMPLIANCE_PROFILE="GDPR"

连接到克劳德桌面

{
  "mcpServers": {
    "elastic-pii-proxy": {
      "command": "node",
      "args": ["/absolute/path/to/dist/stdio.mjs"],
      "env": {
        "UPSTREAM_MCP_COMMAND": "node",
        "UPSTREAM_MCP_ARGS": "/path/to/elastic-mcp/index.mjs",
        "COMPLIANCE_PROFILE": "GDPR",
        "AUDIT_ENABLED": "true"
      }
    }
  }
}

3.环境变量

变量 必填 默认 描述
UPSTREAM_MCP_COMMAND 生成上游MCP服务器的两个 -- 命令之一(例如。, node)
UPSTREAM_MCP_ARGS — "" 上游命令的参数以空格分隔
UPSTREAM_MCP_URL 已运行的上游MCP服务器的两个HTTP/SSE URL之一
COMPLIANCE_PROFILE — GDPR 主动合规概况: GDPR
AUDIT_ENABLED — true 向stderr发送结构化JSON审核条目
COMPREHEND_ENABLED — false 启用第2阶段AWS Comprehend NER编辑
AWS_REGION — us-east-1 用于理解API调用的AWS区域

要么 UPSTREAM_MCP_COMMAND 或 UPSTREAM_MCP_URL 必须设置;如果两者都没有提供,代理将在启动时抛出。


4.合规概况

合规性配置文件选择哪些编校阶段处于活动状态。

简介 第一阶段(正则表达式) 第二阶段(理解NER) 重点
GDPR ✓ ✓ (启用时) 姓名、地址、日期、护照/驾驶员ID
DORA ✓ ✗ 仅限于正则表达式;运营/财务数据
PCI_DSS ✓ ✗ 仅限于正则表达式;支付卡数据焦点
full ✓ ✓ (启用时) 所有阶段,所有实体类型

第一阶段——同步正则表达式 启用后始终运行。盖子:

PII类型 示例输入 屏蔽输出
信用卡 4111 1111 1111 1111 **** **** **** 1111
伊班 DE89370400440532013000 DE89****3000
SSN 123-45-6789 ***-**-****
电子邮件 john.doe@bank.com j***@bank.com
电话 +1 555-123-4567 +15***67

信用卡检测使用Luhn验证来避免随机16位序列的误报。

第二阶段——AWS理解NER 当两者同时运行时 COMPREHEND_ENABLED=true 并且该配置文件具有 stage2: true。捕获正则表达式无法捕获的上下文PII:

PII类型 示例 屏蔽输出
全名 John Doe [REDACTED:NAME]
地址 42 Main St [REDACTED:ADDRESS]
IP地址 192.168.1.101 [REDACTED:IP_ADDRESS]

5.中间件执行顺序

管道采用 compose([auditMW, piiToolMW]) --Koa风格的洋葱模型 第一个元素是最外层.

compose([auditMW, piiMW])

Request in ──► auditMW.enter ──► piiMW.enter ──► upstream
                                                     │
Response  ◄── auditMW.exit  ◄── piiMW.exit  ◄───────┘
             (logs clean)       (redacts PII)

这种排序保证了审计跟踪永远不会包含原始PII——它从已经编辑的结果中读取 piiMW 返回。

用于资源读取的组合管道是 compose([piiResourceMW]) --那里没有审计中间件,因为资源是静态引用内容(不是查询结果)。


6.添加中间件

每个中间件都是一个纯函数——没有类继承,没有全局状态。

import type { Middleware } from './src/proxy/middleware.js';
import type { CallToolRequest, CallToolResult } from '@modelcontextprotocol/sdk/types.js';

// 1. Define the type alias for readability
type ToolCallMiddleware = Middleware<CallToolRequest, CallToolResult>;

// 2. Write a factory function that returns the middleware
export function createMyMiddleware(config: MyConfig): ToolCallMiddleware {
  return async (req, next) => {
    // — before upstream —
    const result = await next(req);
    // — after upstream (result is already processed by inner layers) —
    return result;
  };
}
// 3. Wire it into the pipeline in src/mastra/stdio.ts
import { compose } from './proxy/middleware.js';

const myMW = createMyMiddleware(myConfig);

// Outermost first — myMW sees the result after piiMW has already redacted it
const toolPipeline = compose([auditMW, myMW, piiToolMW]);

中间件可以:

  • 转换请求 在通过之前 next (例如,添加元数据)
  • 转换响应 之后 next 返回(例如,编辑、过滤、丰富)
  • 短路 (早点回来,不打电话 next例如,缓存命中)
  • 处理错误 (捕获自 next、记录、重新抛出或返回错误结果)

7.安全与合规

审计跟踪

每次工具调用都会向stderr生成一个结构化的JSON行 之后 PII编辑:

{
  "timestamp": "2026-02-15T10:30:00.000Z",
  "upstream_tool": "elastic_search",
  "compliance_profile": "GDPR",
  "input_parameters": "{\"index\":\"transactions-*\",...}",
  "output_size_bytes": 4521,
  "redaction_count": 3,
  "redacted_types": ["credit_card", "email"],
  "execution_time_ms": 245,
  "status": "success"
}

输入参数被截断为500个字符。审计日志从不包含原始PII,它总是反映编辑后的状态。

日志中没有原始PII

审计中间件是 外部 图层(compose([auditMW, piiMW])).等到 auditMW.exit 跑, piiMW 已对响应进行了编辑。这在结构上是由组合顺序而不是惯例来执行的。


8.测试

# Unit tests (52 tests across 7 files)
npm test

# Manual PII redaction demo (no upstream needed)
npm run test:redaction

# Build
npm run build:mcp

测试覆盖范围:

文件 测试内容
src/proxy/__tests__/middleware.test.ts compose() 排序、错误传播、双下一步保护
src/middlewares/__tests__/complianceProfiles.test.ts 配置文件选择、阶段标志、未知配置文件回退
src/middlewares/__tests__/piiRedaction.test.ts 电子邮件/SSN编辑、非文本传递、错误结果传递、元数据注入
src/middlewares/__tests__/audit.test.ts 日志格式、编辑后排序、错误记录、禁用记录器
src/lib/__tests__/auditLogger.test.ts JSON格式、截断、stderr路由
src/lib/__tests__/piiRedaction.test.ts 模式准确性、Luhn验证、递归遍历
src/lib/__tests__/comprehendClient.test.ts 堵塞、实体编辑、预过滤器短路

9.项目结构

src/
├── lib/
│   ├── config.ts               # ProxyConfig — env var loader
│   ├── auditLogger.ts          # AuditLogger — structured JSON to stderr
│   ├── piiRedaction.ts         # Stage 1 regex redaction engine
│   ├── comprehendClient.ts     # Stage 2 AWS Comprehend NER wrapper
│   ├── types.ts                # ToolResult<T> discriminated union (dismatch)
│   └── __tests__/
├── proxy/
│   ├── middleware.ts           # Middleware<Req,Res> type + compose()
│   ├── backendClient.ts        # createBackendClient() — MCP SDK Client factory
│   ├── core.ts                 # startProxy() — wires MCPServer + backend + pipelines
│   └── __tests__/
├── middlewares/
│   ├── complianceProfiles.ts   # Profile definitions + getProfile()
│   ├── piiRedaction.ts         # createPiiToolMiddleware() + createPiiResourceMiddleware()
│   ├── audit.ts                # createAuditMiddleware()
│   └── __tests__/
└── mastra/
    └── stdio.ts                # Entry point — composes pipeline, boots proxy
scripts/
└── test-redaction.ts           # Manual PII demo script

10.许可证

MIT——免费使用、修改和分发。