FortiManager代码模式MCP服务器
状态:稳定(v1.0.0)-经过152次测试,针对实时FortiManager v7.6.6进行了验证。
 
一 MCP(模型上下文协议) 服务器 Fortinet FortiManager 使用 代码模式 模式——只需要2个工具,而不是590+。
该服务器没有将每个API端点包装为单独的工具(消耗大约118K个上下文令牌),而是仅公开 search 和 executeAI代理编写JavaScript代码,在安全的环境中运行 QuickJS WASM沙盒 查询API规范或执行实时FortiManager JSON-RPC调用。
为什么是代码模式?
| 方法 | 工具 | 上下文标记 | API覆盖范围 |
|---|---|---|---|
| 传统MCP(每个端点1个工具) | 590+ | ~118000 | 已满 |
| 代码模式(本项目) | 2 | ~1,000 | 满的 |
减少约99% 在保持API全面覆盖的情况下,在上下文令牌中。
代码模式模式是由 Cloudflare的MCP服务器 并在此适用于FortiManager JSON-RPC API。
特性
search-通过沙盒JavaScript查询FortiManager API规范(URL、对象、属性、方法、错误代码)execute-通过带有的沙盒JavaScript运行实时FortiManager JSON-RPC API调用fortimanager.request()代理- 双API版本支持 --规范生成器支持FortiManager 7.4.x和7.6.x
- QuickJS WASM沙盒 --内存/CPU受限的代码执行,没有主机访问权限
- 双重运输 --Stdio(适用于Claude桌面/本地开发)和Streamable HTTP(适用于Docker/生产)
- Docker就绪 --带健康检查的多阶段Alpine构建
- 针对实时FortiManager进行测试 --152项测试(66个单元+86个集成)通过FMG v7.6.6
- 加强安保 --HTTP超时、响应验证、沙盒方法/参数验证、日志上限、代码大小限制
重要提示:要求API规范
如果不首先生成API规范文件,此服务器将无法工作。
API规范文件来源于Fortinet的FortiManager JSON API参考文档,该文档是专有的,不能重新分发。您必须自己下载HTML文档并在本地生成规范。
步骤1:下载API参考资料
- 去 Fortinet开发者网络(FNDN): https://fndn.fortinet.net
- 您需要一个Fortinet帐户(可供合作伙伴、客户和NFR持有人使用)
- 导航至 FortiManager → JSON API参考
- 下载FortiManager版本(7.4.x或7.6.x)的HTML参考档案
步骤2:提取HTML文件
提取下载的存档并将HTML文件放置在 docs/api-reference/ 目录:
docs/api-reference/
├── FortiManager-7.4.9-JSON-API-Reference/
│ └── html/
│ ├── adomobj-errors.htm
│ ├── adomobj-methods.htm
│ └── ... (all .htm files)
└── FortiManager-7.6.5-JSON-API-Reference/
└── html/
├── adomobj-errors.htm
├── adomobj-methods.htm
└── ... (all .htm files)您只需要计划使用的版本。文件夹名称必须与上述模式匹配。
步骤3:生成规范
npm run generate:spec这将解析HTML文档并生成:
src/spec/fmg-api-spec-7.4.json(约99 MB)src/spec/fmg-api-spec-7.6.json(约127 MB)
步骤4:构建
npm run build构建步骤将生成的规范文件复制到 dist/spec/。服务器现在可以使用了。
快速开始
先决条件
来源(推荐)
# Clone the repository
git clone https://github.com/jmpijll/fortimanager-code-mode-mcp.git
cd fortimanager-code-mode-mcp
# Install dependencies
npm install
# Generate API spec (requires HTML docs in docs/api-reference/ — see above)
npm run generate:spec
# Build
npm run build
# Configure environment
cp .env.example .env
# Edit .env with your FortiManager details
# Start (stdio mode)
FMG_HOST=https://fmg.example.com FMG_API_TOKEN=your-token npm start
# Or development mode with hot reload
FMG_HOST=https://fmg.example.com FMG_API_TOKEN=your-token npm run devDocker(推荐用于HTTP)
备注:在构建Docker镜像之前,您必须生成规范文件。Dockerfile从以下位置复制它们 src/spec/ 在构建时。# Clone and install
git clone https://github.com/jmpijll/fortimanager-code-mode-mcp.git
cd fortimanager-code-mode-mcp
npm install
# Generate API spec (requires HTML docs — see above)
npm run generate:spec
# Configure environment
cp .env.example .env
# Edit .env with your FortiManager details
# Run with Docker Compose
docker compose up -d --build
# Verify
curl http://localhost:8000/health
# → {"status":"ok","version":"1.0.0"}VS代码副本
先决条件:您必须首先使用生成的规范文件从源代码构建服务器。使用 "command": "node" 通往您当地建筑的道路。创建 .vscode/mcp.json 在您的工作空间中:
{
"servers": {
"fortimanager": {
"type": "stdio",
"command": "node",
"args": ["/path/to/fortimanager-code-mode-mcp/dist/index.js"],
"env": {
"FMG_HOST": "https://fortimanager.example.com",
"FMG_PORT": "443",
"FMG_API_TOKEN": "your-api-token-here",
"FMG_VERIFY_SSL": "true",
"FMG_API_VERSION": "7.6",
"MCP_TRANSPORT": "stdio"
}
}
}
}克劳德桌面(stdio)
先决条件:您必须首先使用生成的规范文件从源代码构建服务器。
添加到您的Claude Desktop配置(claude_desktop_config.json):
{
"mcpServers": {
"fortimanager": {
"command": "node",
"args": ["/path/to/fortimanager-code-mode-mcp/dist/index.js"],
"env": {
"FMG_HOST": "https://fortimanager.example.com",
"FMG_API_TOKEN": "your-api-token",
"FMG_API_VERSION": "7.6",
"MCP_TRANSPORT": "stdio"
}
}
}
}建筑
┌──────────────────────────────────────────────────────────────┐
│ AI Agent / LLM │
│ │
│ "Find all firewall address objects and list their URLs" │
└────────────────────────┬─────────────────────────────────────┘
│ MCP Protocol (stdio or HTTP)
▼
┌──────────────────────────────────────────────────────────────┐
│ MCP Server (Node.js) │
│ │
│ ┌─────────────────────┐ ┌────────────────────────────────┐ │
│ │ search tool │ │ execute tool │ │
│ │ │ │ │ │
│ │ JS code → QuickJS │ │ JS code → QuickJS (async) │ │
│ │ sandbox │ │ sandbox │ │
│ │ │ │ │ │
│ │ Globals: │ │ Globals: │ │
│ │ • specIndex │ │ • fortimanager.request() │ │
│ │ • getObject() │ │ • console.log() │ │
│ │ • moduleList │ │ │ │
│ │ • errorCodes │ │ Proxies to ──┐ │ │
│ │ • specVersion │ │ │ │ │
│ └─────────────────────┘ └───────────────┼───────────────┘ │
│ │ │
│ ┌─────────────▼──────────────┐ │
│ │ FortiManager JSON-RPC │ │
│ │ Client (fetch + auth) │ │
│ └─────────────┬──────────────┘ │
└────────────────────────────────────────────┼─────────────────┘
│ HTTPS JSON-RPC
▼
┌────────────────────┐
│ FortiManager │
│ (7.4.x / 7.6.x) │
└────────────────────┘工具使用示例
search -查询API规范
// Find all firewall-related objects
specIndex.filter(function(o) {
return o.name.includes('firewall');
}).map(function(o) {
return { name: o.name, urls: o.urls, type: o.type };
})// Get full details of a specific object (all attributes, URLs, methods)
getObject('firewall/address')// Search by attribute name
specIndex.filter(function(o) { return o.attributeNames.includes('srcaddr'); }).map(function(o) { return o.name; })// Find objects by URL pattern
specIndex.filter(function(o) {
return o.urls.some(function(u) { return u.includes('/dvmdb/'); });
}).map(function(o) { return { name: o.name, urls: o.urls }; })execute -致电FortiManager API
// List all ADOMs
var resp = fortimanager.request('get', [{ url: '/dvmdb/adom' }]);
resp.result[0].data;// Get system status
var resp = fortimanager.request('get', [{ url: '/sys/status' }]);
resp.result[0].data;// Create a firewall address object
var resp = fortimanager.request('add', [
{
url: '/pm/config/adom/root/obj/firewall/address',
data: {
name: 'web-server',
subnet: ['10.0.1.100', '255.255.255.255'],
},
},
]);
resp.result[0].status;// Device proxy — get interfaces from a managed FortiGate
var resp = fortimanager.request('exec', [
{
url: '/sys/proxy/json',
data: {
target: ['/adom/root/device/my-fortigate'],
action: 'get',
resource: '/api/v2/monitor/system/interface',
},
},
]);
resp.result[0].data;配置
| 变量 | 必填 | 默认 | 描述 |
|---|---|---|---|
FMG_HOST | 是 | -- | FortiManager URL(例如。, https://fmg.example.com) |
FMG_PORT | 没有 | 443 | HTTPS端口 |
FMG_API_TOKEN | 是 | - | 用于身份验证的API令牌(如何创建) |
FMG_VERIFY_SSL | 没有 | true | 验证TLS证书(false 对于自签名证书) |
FMG_API_VERSION | 没有 | 7.6 | API规范版本(7.4 或 7.6) |
MCP_TRANSPORT | 没有 | stdio | 运输方式(http 或 stdio) |
MCP_HTTP_PORT | 没有 | 8000 | HTTP服务器端口(仅与 http 运输) |
发展
# Install dependencies
npm install
# Run unit tests (66 tests across 5 suites)
npm test
# Run integration tests against a live FortiManager (requires .env)
npx tsx scripts/live-test.ts
# Lint
npm run lint
# Type check
npm run typecheck
# Format code
npm run format
# Build
npm run build
# Re-generate API specs from HTML docs
npm run generate:spec项目结构
src/
├── client/ # FortiManager JSON-RPC client
│ ├── types.ts # Request/response types, error codes
│ ├── auth.ts # Token & session auth providers
│ └── fmg-client.ts # HTTP client (get/set/add/update/delete/exec/clone/move)
├── executor/ # QuickJS WASM sandbox executors
│ ├── types.ts # ExecuteResult, LogEntry, ExecutorOptions
│ ├── executor.ts # Base executor (lifecycle, console capture, limits)
│ ├── search-executor.ts # Spec index + getObject() injection
│ └── code-executor.ts # fortimanager.request() proxy (async)
├── server/ # MCP server and transport
│ ├── server.ts # McpServer with search + execute tools
│ └── transport.ts # Stdio + Streamable HTTP transports
├── spec/ # Generated API spec JSON files (git-ignored, generated locally)
│ ├── fmg-api-spec-7.4.json # 72 modules, 17,426 objects, 38,586 URLs
│ └── fmg-api-spec-7.6.json # 82 modules, 22,060 objects, 49,285 URLs
├── types/ # Shared type definitions
├── config.ts # Zod-validated environment config
├── __tests__/ # Unit tests (66 tests across 5 suites)
│ └── fixtures/ # Sample spec, response builders
└── index.ts # Entry point
scripts/
├── generate-spec.ts # HTML docs → JSON spec generator
├── e2e-test.ts # End-to-end scenario tests (live FMG)
├── live-test.ts # Integration test suite (86 tests against live FMG)
└── spec-coverage.ts # API spec coverage report & live URL validation安全
- 沙盒执行 --所有代理生成的代码都在具有强制内存(64 MB)和CPU(30秒超时)限制的QuickJS WASM沙箱中运行。无法访问
process,require,fs,或任何Node.js API。 - 主机中没有eval --宿主Node.js进程从不调用
eval()或new Function()。只有WASM沙箱执行不受信任的代码。 - HTTP请求超时 -所有FortiManager API调用的30秒超时可防止无限期挂起。
- 响应形状验证 --JSON-RPC响应体在处理之前经过验证,防止因格式错误的响应而崩溃。
- 沙盒方法验证 --仅允许使用FMG方法(
get,set,add,update,delete,exec,clone,move,replace)从沙盒代码转发。 - 沙盒参数验证 --沙盒代码中的参数被验证为具有所需参数的数组
url转发前的字段。 - 原木积累上限 --控制台输出的上限为1 MB/1000个条目,以防止主机内存耗尽。
- 代码输入大小限制 --超过100KB的代码输入在执行前会被拒绝。
- TLS验证 --默认启用(
FMG_VERIFY_SSL=true).仅对使用自签名证书的开发禁用。 - 基于令牌的身份验证 -通过使用FortiManager API代币
Authorization: Bearer头球未存储密码。 - 每次执行的新上下文 --每次工具调用都会获得一个新的沙盒上下文。执行死刑之间没有国家泄密。
- API调用限制 -每个沙箱执行最多50个API调用,以防止失控循环。
- 响应截断 --超过100 KB的结果将被截断,并提供缩小查询范围的指导。
- 启动健康检查 --FortiManager连接在启动时进行验证(非致命)。
- 优雅关闭 --stdio和HTTP传输都处理SIGINT/SIGTERM以实现干净关机。
看 安全.md 用于漏洞报告。
文档
致谢
该项目由以下人员共同开发 杰米·范德皮尔 和 (克劳德)。
灵感来源:
- Cloudflare MCP服务器 --开创了MCP服务器的代码模式(2个工具而不是数百个)
- 福特经理mcp --我们早期用于FortiManager的传统MCP服务器(每个端点一个工具,现已存档),这表明需要一种更高效的令牌方法
