Skip to main content
Glama
ivantagesam

OpsBridge MCP

by ivantagesam

OpsBridge MCP

一个模型上下文协议(MCP)服务器,为AI客户端提供对业务客户及支持工单数据的受控、可审计访问——包括一个真实的写入操作,该操作由服务器强制执行的审批检查门控,而非提示指令。

这是一个聚焦的技术演示,而非产品。 它是一个作品集项目,旨在做好一件事:在TypeScript中正确实现一个MCP服务器,并具备将仅能运行的演示与真正可安全指向LLM的演示区分开来的特定工程纪律——模式验证、参数化SQL、在应用代码中强制执行的审批门,以及审计跟踪,全部对照真实SDK和真实协议验证,而非假设。它部署在任何地方,没有真实客户,也声称生产就绪——请参阅限制生产环境我会做的改动以了解确切界限。

这解决了什么问题

AI客户端日益被期望对真实系统采取真实行动,而不仅仅是回答问题。这产生了一个具体的工程问题:如何让模型读取实时业务数据并执行一项有后果的操作,而不会(a)给予其不受限制的数据库访问权限,或(b)信任提示是“模型建议了此操作”与“此操作实际发生”之间的唯一屏障?

OpsBridge是对该问题在一个具体场景下的小而完整的回答:一个支持工单系统。它精确暴露了AI助手所需的数据(客户、工单),以及恰好一种更改任何内容的方式(创建工单)——而该写入路径无法执行,除非调用者明确提供approved: true,该检查在服务器代码中运行,无论模型“决定”什么。项目中的其他一切——模式、错误处理、审计日志——都旨在使这一保证真正可信。

Related MCP server: SQLite MCP Server

MCP在此架构中的作用

Model Context Protocol是使AI客户端(Claude Code、Claude Desktop、MCP Inspector或任何其他支持MCP的客户端)能够发现此服务器可执行的操作并调用它,而无需为每个客户端编写自定义集成代码的层。具体而言,在此项目中,MCP负责:

  • 工具发现——服务器通告search_customersget_customerlist_customer_ticketscreate_support_ticket,每个工具都有JSON-Schema描述的输入和输出,由本项目的Zod模式自动生成。

  • 结构化请求/响应契约——每次工具调用在项目代码运行前都会根据其模式进行验证,每个响应要么是正常结果,要么是格式良好的isError: true结果——绝不会是原始异常或格式错误的回复。

  • 传输——通过stdio的JSON-RPC 2.0。客户端将node dist/index.js作为子进程启动,并通过stdin/stdout与其通信;没有网络端口。

MCP不执行任何实际工作——它是通用AI客户端无需定制胶水代码即可使用此服务器的原因。业务逻辑、验证和安全保证是本项目自身的。

架构

flowchart TD
    Client["Claude Code / MCP Client"]
    Protocol["MCP Protocol<br/>(JSON-RPC over stdio)"]
    Server["OpsBridge MCP Server<br/>src/server.ts · src/index.ts"]
    Tools["Tool Layer<br/>src/tools/*.ts"]
    Approval["Approval / Validation<br/>src/domain/*.ts"]
    DB[("SQLite Database<br/>src/db/*.ts")]
    Audit["Audit Log (stderr)<br/>src/lib/audit.ts"]

    Client --> Protocol --> Server --> Tools --> Approval --> DB
    Tools -.->|every call, success or failure| Audit
src/
  db/        SQLite schema, synthetic seed data, idempotent seeding
  domain/    Repository functions (customers, tickets) — plain TS, no MCP knowledge
  tools/     One file per MCP tool: Zod schema, audit-log wrapper, thin handler
  lib/       Audit logging (lib/audit.ts) and typed error classes (lib/errors.ts)
  server.ts  Builds the McpServer and registers all tools
  index.ts   Entrypoint — opens/seeds the DB, connects stdio transport

分层是有意且单向的:每层仅了解其下一层,domain/不导入@modelcontextprotocol/sdk中的任何内容——它是基于better-sqlite3数据库的纯TypeScript。这使得测试套件能够测试真实的端到端工具调用路径(真实的MCP Client与真实的McpServer通信),而不是模拟层边界。完整说明,包括精确代码路径:docs/architecture.md

暴露的工具

工具

类型

用途

search_customers

读取

按姓名或电子邮件查找客户(部分匹配,不区分大小写)

get_customer

读取

按ID获取单个客户的详细信息

list_customer_tickets

读取

列出客户的工单,可选按状态筛选

create_support_ticket

写入

创建新工单——需要显式approved: true

由SQLite支持,使用合成、虚构数据:10个客户,18个种子支持工单。

技术栈

选择

原因

语言

TypeScript,严格模式 + noUncheckedIndexedAccess / exactOptionalPropertyTypes

捕获此项目关注的层边界处的真实错误(可选字段、索引访问)

MCP SDK

@modelcontextprotocol/sdk 1.30.0

当前发布的主要版本——截至撰写时没有v2;根据安装包自身的.d.ts文件验证,而非教程

模式验证

zod ^4

运行时验证和发送给客户端的JSON Schema的单一事实来源

数据库

better-sqlite3 ^12(同步)

对于单进程本地服务器,无需异步驱动/连接池复杂性;使用^12而非更新的13.x,因为13.x需要Node 22+,而此项目目标为Node 20+

运行时

Node.js 20+

声明的项目基线

测试

vitest ^4

通过InMemoryTransport将真实的MCP Client连接到真实的McpServer——参见测试

代码检查

eslint ^10 + typescript-eslint ^8

typescript-eslint尚不支持TypeScript 7(新的基于Go的编译器),因此TypeScript被固定为5.9.x系列——这是刻意的兼容性选择,而非疏忽

开发运行器

tsx

在开发期间无需构建步骤即可直接运行src/index.ts

审批机制

create_support_ticket是系统中唯一有后果的操作,因此它是本项目添加硬门的地方:

// src/domain/tickets.ts
export function createSupportTicket(db, input: CreateTicketInput): Ticket {
  if (input.approved !== true) {
    throw new ApprovalRequiredError(
      "Ticket creation was not approved. Set approved=true to confirm this action before it is created.",
    );
  }
  // ... only reaches the INSERT after this point
}

两件事使其成为实际的强制机制而非建议:

  1. 它在域层运行,位于MCP工具层之下,在任何SQL执行之前——从工具处理器到数据库INSERT不存在跳过它的代码路径。

  2. approved是工具输入模式中的必需布尔值,而非可选。省略它,调用会在代码运行前因模式验证失败;传递false,则在此处被拒绝。

工具描述还要求模型先与用户确认——但这是模型行为的建议性文本,而非系统安全的原因。即使模型忽略描述并直接调用工具,该保证仍然成立;服务器而非提示是最后一道防线。

这不保证的是: 人类实际设置了该标志——approved: true只是模型可能自行提供的另一个参数,而人类从未看到该请求。完全弥合这一差距需要服务器强制交互式确认往返回人类(MCP elicitation);本项目有意不添加此功能,因为对于本项目不声称提供的保证而言,这是一个真实的交互模型更改。参见限制

安全考虑

  • 审批在应用程序代码中强制执行,而非提示——参见上文。

  • 每次工具调用都会审计记录到stderr(src/lib/audit.ts,通过withAudit()包装器应用于所有四个工具):工具名称、时间戳、成功/失败,以及非敏感标识符(适用时为customer_id);create_support_ticket行还记录调用是否被批准。绝不记录调用的敏感内容——不记录工单主题/描述、原始搜索查询文本、电子邮件/电话/姓名。

  • 所有SQL均通过better-sqlite3预处理语句参数化——无字符串拼接,因此即使输入最终来自LLM,也不存在SQL注入面。search_customersLIKE模式还转义了%/_,使搜索文本按字面匹配,而非作为通配符(否则仅查询"%"将返回每一行)。

  • 输入在到达任何业务逻辑之前使用Zod验证——长度限制、priority/status的枚举约束——以清晰的错误拒绝格式错误的输入,而非将其传递。

  • 存储的工单文本被框架为数据,而非指令。 subject/description是自由文本,现在创建的工单会被后续的list_customer_tickets调用逐字读取——这是一个二阶提示注入向量。响应文本明确指出此内容是存储的客户输入,而非指令。这是一种缓解措施,而非保证。

  • 无身份验证或授权。 这是一个本地、单用户演示——任何能启动该进程的人都能完全访问每个工具,包括完整的客户PII。此处明确超出范围;在接触真实、多租户数据之前必须更改。

  • 项目中无任何秘密。 无API密钥、令牌或凭据;唯一的外部依赖是本地SQLite文件,该文件已被gitignore。

示例Claude交互

连接后的读取路径提示:

  • “搜索名为Chen的客户。”

  • “获取客户cust_004的完整详细信息。”

  • “cust_005有哪些未关闭的工单?”

有趣的是写入路径:

你: “为cust_002创建高优先级支持工单,关于其跟踪号码未同步——但在实际创建前先与我确认。”

预期行为: 模型按需调用search_customers/get_customer,然后要么在调用create_support_ticket前要求你确认,要么使用approved false/省略调用一次,被拒绝,并将提议的工单返回给你。无论哪种方式,在您实际同意且模型再次以approved: true调用之前,不会写入任何内容。

更多脚本化演练,包括强制拒绝路径以直接查看原始强制消息:docs/demo-script.md

本地设置

需要Node.js 20+

npm install
npm run db:seed     # creates and seeds data/opsbridge.db (10 customers, 18 tickets)
npm run build        # compiles TypeScript to dist/
npm run dev           # runs src/index.ts directly with tsx (auto-seeds on first run)
# or, after `npm run build`:
npm start              # runs dist/index.js

服务器通过stdio通信——无HTTP端口,无法直接浏览。

连接到 Claude Code: 本仓库包含一个项目范围的 .mcp.json(通过 claude mcp add opsbridge --scope project -- node dist/index.js 生成,因此它正是 CLI 自身产出的内容,而非手写的)。先构建,然后批准一次:

npm run build
claude          # prompts to trust this project's .mcp.json server on first run — approve it
claude mcp list # should show: opsbridge: node dist/index.js - ✔ Connected

连接任何其他 MCP 客户端(Claude Desktop 等)——大多数读取带有 command/args 对的 JSON 配置:

{
  "mcpServers": {
    "opsbridge": {
      "command": "node",
      "args": ["/absolute/path/to/opsbridge-mcp/dist/index.js"]
    }
  }
}

在没有完整客户端的情况下手动测试 —— MCP Inspector,版本被刻意固定(未指定版本的 npx @modelcontextprotocol/inspector 可能会解析到过时的缓存构建,而不是当前版本):

npx @modelcontextprotocol/inspector@2.3.0 node dist/index.js       # web UI
npx @modelcontextprotocol/inspector@2.3.0 --cli node dist/index.js -- --method tools/list   # headless

测试

npm test        # vitest — 33 tests across 6 files
npm run typecheck
npm run lint

测试通过 SDK 的 InMemoryTransport 将真实的 MCP Client 连接到真实的 McpServer,每个测试使用全新的内存 SQLite 数据库(tests/helpers.ts)——实际演练了真实客户端所经历的请求 → Zod 验证 → 工具处理器 → 响应路径,而不仅仅是孤立地测试领域函数。覆盖范围包括:成功和空结果的搜索、客户未找到、带/不带状态筛选的工单列表、每个工具的无效输入、以 approved: false 和完全省略 approved 两种方式被拒绝的工单创建、成功创建、重复提交安全性、LIKE 通配符转义、提示注入框架文本,以及每个工具的审计日志内容(包括 PII 永远不会出现在日志行中)。

限制

为聚焦演示而刻意裁剪的范围,而非疏忽:

  • 没有身份验证、授权或按用户的数据范围划分 —— 参见安全考虑。

  • 审批标志不是经过验证的人类信号 —— 它是一个模型可以自行设置的布尔值;请参阅批准机制。

  • 无分页 —— 搜索最多返回 10 条结果;工单列表无上限,但数据集很小。

  • 没有更新或删除工具 —— 只有工单创建是写操作。

  • 仅 stdio 传输 —— 没有 HTTP/SSE,没有远程部署方案。

  • create_support_ticket 上没有速率限制或幂等键 —— 重试的调用会创建第二个独立的工单,而不是被去重。

  • SQLite,单进程 —— 没有连接池,除了 CREATE TABLE IF NOT EXISTS 之外没有迁移工具。

  • 审计日志是本地 stderr 流 —— 不发送到任何地方,不可查询,没有保留策略。

生产环境中我会做的改动

如果这个模式曾真正指向真实客户而不是合成演示数据:

  • 从 stdio 迁移到支持 OAuth bearer 认证的 Streamable HTTP,按租户/客户划分范围 —— SDK 已经支持这种传输;当前的 stdio 模型隐式信任任何能启动该进程的人,这仅适用于本地演示,其他地方都不行。

  • 添加真正的授权,将经过认证的调用者映射到他们可以访问的客户/工单 —— 目前每个工具都是无范围的。

  • 让审批可验证,而不仅仅是存在 —— 使用 MCP 引导来强制向人类进行真实的往返确认,或要求由模型控制之外的单独确认步骤铸造的短期令牌。

  • 将 SQLite 替换为 Postgres,使用连接池和真正的迁移工具。

  • 将审计日志发送到持久且可查询的地方(而不是 stderr),并配备与其审计内容相适应的保留和访问控制。

  • 在写入路径上添加速率限制和幂等键

  • search_customerslist_customer_tickets 添加分页

  • 添加可观测性 —— 每个工具的延迟、错误率和调用量。

  • 在 CI 中对每次更改运行类型检查/测试/lint,而不仅仅是在本地按需运行。

这里没有实现任何这些 —— 这个项目的意义是以小规模正确演示该模式,而不是预先构建真实部署需要但演示不需要的基础设施。

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Runtime permission, approval, and audit layer for AI agent tool execution.

  • Deterministic compliance and vertical knowledge bases for autonomous agents. Free 24hr trial.

  • Pre-action allow/deny for AI agents. 24 statutes, 13 jurisdictions: EU AI Act, GDPR, DPDP.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ivantagesam/opsbridge-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server