使用说明
MCP网关:发现+生成LangGraph工作流
演示存储库:该项目演示了用于API端点发现和MCP工具生成的LangGraph工作流编排。它仅用于教育和参考目的。
一个强大的两阶段工作流系统,可自动从规范或文档中发现API端点,并生成符合JSON Schema Draft-07的MCP(模型上下文协议)工具定义。
目录
概述
此项目实现了两个可组合的LangGraph工作流:
-
DiscoveryGraph -从以下位置智能地发现API终结点:
- OpenAPI/Swagger规范(JSON/YAML)
- 文档网站(通过网络爬虫)
- 自由格式文本文件(通过LLM提取)
-
生成图 -生成生产就绪的MCP工具定义,包括:
- 符合JSON模式Draft-07的参数模式
- 全面的验证和错误处理
- 从端点到工具的自动化工作流程
该系统利用 LangGraph 用于工作流编排和 LangChain LLM操作。这两个图都在没有中断的情况下运行到完成,端点选择在编排层中处理。
主要特点
- 多源发现:处理OpenAPI规范、web文档和非结构化文本
- 混合萃取:将正则表达式模式匹配与LLM驱动的提取相结合
- 智能网络爬行:具有域边界和速率限制的站点地图感知爬行
- 智能重复数据删除:对发现的端点进行标准化和重复数据消除
- 架构验证:JSON模式草稿-07合规性检查
- 状态持久性:用于工作流恢复的基于SQLite的检查点
- 标准化命名:一致
VENDOR__RESOURCE__VERB工具命名约定
建筑
双图工作流系统
+-------------------------------------------------------------------+
| INPUT SOURCES |
| * OpenAPI/Swagger Specs (JSON/YAML) |
| * Documentation URLs |
| * Free-form text files |
+-----------------------------+-------------------------------------+
|
v
+-------------------------------------------------------------------+
| DISCOVERY GRAPH |
| Discovers and catalogs API endpoints |
+-----------------------------+-------------------------------------+
|
v
[Orchestration Layer]
(Endpoint Selection)
|
v
+-------------------------------------------------------------------+
| GENERATION GRAPH |
| Generates MCP tool definitions |
+-----------------------------+-------------------------------------+
|
v
>> MCP Tools (JSON) <<
状态管理
系统使用 类型化字典 类型安全状态管理的模式:
发现状态:
input:输入配置(文件或root_url)discovery:发现的端点、页面和目录
世代状态:
selection:从发现中选择的端点generation:工作项、生成的工具和错误
编排模式
这两个图都设计为在没有中断的情况下运行到完成:
- 发现图 完全运行并输出目录中发现的所有端点
- 业务流程层 (in
main.py)处理端点选择:- 向用户显示发现的端点
- 收集用户的端点选择
- 将所选端点传递给生成图
- 生成图 完全运行并输出经过验证的MCP工具定义
这种设计将关注点分开:图形处理工作流逻辑,而编排层处理用户交互。
工作流详细信息
发现图流
发现图使用 条件分支 通过两条互斥路径之一路由输入:
classify_input
|
v
[Route by input_type]
/ \
/ \
file url
/ \
v v
parse_files discover_from_web
\ /
\ /
v v
endpoint_extractor
|
v
normalize_and_dedup
|
v
summarize_for_ui
|
v
END
条件路由逻辑:
- 之后
classify_input确定input_type(“文件”或“url”) - 该图指向 要么
parse_files或discover_from_web(从来没有两者) - 两个分支在
endpoint_extractor用于统一处理 - 这确保了只执行相关路径,提高了效率和清晰度
节点分解
| 节点 | 目的 | 输入 | 输出 |
|---|---|---|---|
| classify_input | 确定输入是基于文件还是基于URL | 原始输入配置 | 分类输入类型 |
| 解析器文件 | 解析OpenAPI规范(JSON/YAML)或从文本中提取 | 文件路径 | 从文件中提取原始端点 |
| discover_from_web | 通过站点地图或BFS抓取文档网站 | 根URL | 发现的网页 |
| 端点提取器 | 使用正则表达式模式+LLM提取端点 | 网页内容 | 原始端点列表 |
| 正常化_和重复 | 规范化路径、方法并删除重复项 | 原始端点 | 唯一的规范化端点 |
| summarize_for_ui | 按资源对端点进行分组并计算置信度 | 标准化端点 | 组织目录 |
发现节点详细信息
1.classify_input_node (discovery/nodes.py:28)
- 检查输入配置
- 集合
input_type转到“文件”或“url” - 初始化空发现状态结构
2.parse_files_node (discovery/nodes.py:51)
- 仅当input_type为“file”时执行(通过条件路由)
- 尝试解析为JSON/YAML OpenAPI规范
- 回退到LLM提取自由格式文本
- 从OpenAPI提取端点
paths章节 - 优雅地处理多种文件格式
3.discover_from_web_node (discovery/nodes.py:97)
- 仅当input_type为“url”时执行(通过条件路由)
- 首次尝试发现sitemap.xml
- 回退到广度优先抓取(最多10页)
- 尊重域名边界(无外部链接)
- 实现请求之间的限制
- 存储页面内容以进行提取
4.端点提取器节点 (discovery/nodes.py:126)
- 将regex模式应用于常见的API格式:
GET|POST|PUT|DELETE|PATCH /api/...GET|POST|PUT|DELETE|PATCH /v1/...- 回溯包装端点
- 使用LLM从非结构化文档中进行结构化提取
- 存储用于置信度计算的源代码(“regex”或“llm”)
5.正常化_和重复_节点 (discovery/nodes.py:183)
- 创建唯一密钥:
server|method|path - 删除查询字符串和空格
- 生成基于MD5的12个字符的ID
- 保留描述、参数和请求正文
- 追踪信心评分的来源
6.总结_用于_节点 (discovery/nodes.py:238)
- 按资源对端点进行分组(第一个路径段)
- 根据以下内容计算置信度得分(0.0-1.0):
- 源类型(OpenAPI>正则表达式>LLM)
- 描述的存在
- 参数完整性
- 创建分层目录结构
- 提供摘要统计信息
- 完成发现图工作流
生成图形流
生成图由6个节点组成,这些节点将选定的端点转换为经过验证的MCP工具:
plan_work -> schema_synthesis -> compose_tool -> validate
-> aggregate_tools -> finalize -> END
节点分解
| 节点 | 目的 | 输入 | 输出 |
|---|---|---|---|
| 计划工作 | 为每个选定端点创建工作项 | 选定端点ID | 工作项队列 |
| 方案综合 | 使用LLM生成JSON模式参数 | 端点详细信息 | 参数模式 |
| compose_tool | 使用命名 | 模式+端点 | MCP工具对象构建完整的MCP工具结构 |
| 验证 | 根据JSON Schema Draft-07验证模式 | 工具定义 | 仅验证工具 |
| 聚合工具 | 对所有已验证的工具进行排序和聚合 | 单个工具 | 已排序的工具集合 |
| 完成 | 标记完成并提供摘要 | 已验证的工具 | 最终工具列表 |
生成节点详细信息
1.计划_工作_节点 (generation/nodes.py:34)
- 从所选端点ID创建工作项
- 筛选端点以仅包括选定的端点
- 初始化状态跟踪(“待定”、“schema_generated”等)
- 设置错误收集结构
2.模式_合成_节点 (generation/nodes.py:60)
- 为每个端点使用带结构化提示的LLM
- 生成包含4个组的嵌套参数架构:
header-HTTP标头path-路径参数query-查询字符串参数body-请求正文
- 强制JSON模式功能:
- 类型约束和格式
- 受限字段的枚举值
- 最小/最大长度和值约束
- 所需字段规范
- 使用数组表示法的null类型
- 使用自定义元数据增强架构:
visible:UI可见字段数组required:必填字段名additionalProperties:布尔值用于严格验证
- 优雅地处理错误,标记失败的项目
3.组合工具节点 (generation/nodes.py:153)
- 从服务器URL中提取供应商(域或“未知”)
- 从路径中提取资源(版本后的第一段)
- 根据方法+路径分析确定动词
- 编写工具名称:
VENDOR__RESOURCE__VERB(大写) - 根据描述生成人类可读的显示名称
- 构建完整的MCP工具结构:
- 名称、显示名称、描述
- 标签:[供应商,资源,版本,方法]
- 协议:“休息”
- 协议数据:方法、路径、服务器url
- 参数:嵌套架构
- 元数据:来源和置信度得分
4.validate_node (generation/nodes.py:225)
- 创建架构的干净副本(删除自定义
visible现场) - 使用JSON Schema Draft-07进行验证
jsonschema图书馆 - 用途
Draft7Validator.check_schema()用于验证 - 过滤掉无效工具
- 将验证错误记录到错误数组中
- 使用有效工具的自定义字段保留原始架构
5.聚合工具节点 (generation/nodes.py:264)
- 收集所有经过验证的工具
- 按工具名称的字母顺序排序
- 为输出提供一致的排序
6.finalize_node (generation/nodes.py:284)
- 将生成标记为“已完成”
- 提供最终工具计数
- 报告遇到的任何错误
- 返回完整的输出工具列表
安装
此项目使用 紫外线 使用Python 3.12+进行Python包管理。
先决条件
- Python 3.12或更高版本
- 紫外线 包管理器
设置
-
克隆存储库:
git clone <repository-url> cd mcp-gateway-graph-demo -
安装依赖项:
uv sync -
配置环境变量:
创建一个
.env项目根目录中的文件(使用.env.example作为模板):# Required for LLM operations AZURE_OPENAI_API_KEY=your_api_key_here AZURE_OPENAI_API_VERSION=2024-02-15 AZURE_OPENAI_ENDPOINT=https://your-endpoint.openai.azure.com/ # Optional: LangSmith tracing LANGSMITH_API_KEY=your_langsmith_key LANGSMITH_TRACING=true LANGSMITH_PROJECT=mcp-gateway
用法
命令行接口
主CLI通过Click提供了几个命令:
# Show help
uv run python main.py --help
# Run with OpenAPI spec file
uv run python main.py --files api_spec.json --output tools.json
# Run with multiple files
uv run python main.py --files spec1.json --files spec2.yaml
# Run with documentation URL
uv run python main.py --url https://api.example.com/docs --output tools.json
# Run example workflow with mock data
uv run python main.py --example
# Auto-approve mode (non-interactive)
uv run python main.py --files api_spec.json --auto-approve --output tools.json
CLI选项
| 选项 | 描述 |
|---|---|
-f, --files PATH |
API规范文件的路径(允许多个) |
-u, --url TEXT |
要爬网API文档的根URL |
-o, --output PATH |
输出文件路径(默认: mcp_tools.json) |
--auto-approve |
自动选择所有发现的端点(非交互式) |
--example |
使用模拟数据运行示例工作流 |
程序化使用
您还可以直接导入和使用这些模块:
from utils import build_full_workflow
# Build both graphs with checkpointing
discovery_graph, generation_graph = build_full_workflow()
# Run discovery (runs to completion)
config = {"configurable": {"thread_id": "unique-session-id"}}
input_data = {
"input": {"files": ["/path/to/spec.json"]},
"discovery": {}
}
for event in discovery_graph.stream(input_data, config):
print(event)
# Get discovered endpoints from final state
final_state = discovery_graph.get_state(config)
endpoints = final_state.values.get("discovery", {}).get("endpoints_normalized", [])
# Endpoint selection happens in orchestration layer (not in graph)
# Then pass selected endpoints to Generation Graph
项目结构
mcp-gateway-graph-demo/
├── config.py # Configuration, LLM setup, constants
├── main.py # CLI entry point (using Click)
├── .env # Environment variables (not in git)
├── .env.example # Environment template
├── models/
│ ├── __init__.py
│ └── schemas.py # State schemas, Pydantic models
├── discovery/
│ ├── __init__.py
│ ├── nodes.py # 6 discovery node functions
│ ├── helpers.py # OpenAPI parsing, LLM extraction, web crawling
│ ├── graph.py # build_discovery_graph()
│ └── runners.py # Runner utilities
├── generation/
│ ├── __init__.py
│ ├── nodes.py # 6 generation node functions
│ ├── helpers.py # Schema enhancement, vendor extraction, validation
│ ├── graph.py # build_generation_graph()
│ └── runners.py # Runner utilities
├── utils/
│ ├── __init__.py
│ ├── workflow.py # build_full_workflow(), checkpointing
│ └── tools.py # Utility functions
├── tests/
│ ├── __init__.py
│ ├── test_data.py # Mock OpenAPI spec generation
│ └── test_workflow.py # Full workflow test
└── graph-demo.ipynb # Original notebook (reference only)
配置
环境变量
| 变量 | 必填 | 描述 |
|---|---|---|
AZURE_OPENAI_API_KEY |
是 | 用于LLM操作的Azure OpenAI API密钥 |
AZURE_OPENAI_API_VERSION |
是 | API版本(例如“2024-02-15”) |
AZURE_OPENAI_ENDPOINT |
是 | Azure OpenAI端点URL |
LANGSMITH_API_KEY |
否 | 用于跟踪的LangSmith API密钥 |
LANGSMITH_TRACING |
否 | 启用跟踪(“true”/“false”) |
LANGSMITH_PROJECT |
否 | LangSmith项目名称(默认:“mcp-gateway”) |
常量(config.py)
DEFAULT_MODEL = "gpt-4.1"-LLM模型用于提取和生成MAX_CRAWL_PAGES = 20-每个域可抓取的最大页面数CRAWL_DELAY = 0.5-爬网请求之间的秒数LLM_PAGE_SAMPLE_LENGTH = 3000-从长页面中采样的字符
输出格式
生成的MCP工具遵循标准化的JSON结构:
{
"name": "EXAMPLE__FLIGHTS__SEARCH",
"display_name": "Search for available flights",
"description": "Search for flights based on origin, destination, and dates",
"tags": ["example", "flights", "v1", "post"],
"visibility": "public",
"active": true,
"protocol": "rest",
"protocol_data": {
"method": "POST",
"path": "/api/v1/flights/search",
"server_url": "https://api.example.com"
},
"parameters": {
"header": {
"type": "object",
"properties": {
"Authorization": {
"type": "string",
"description": "Bearer token for authentication"
}
},
"required": ["Authorization"],
"visible": ["Authorization"]
},
"path": {
"type": "object",
"properties": {},
"required": [],
"visible": []
},
"query": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"description": "Maximum results to return",
"minimum": 1,
"maximum": 100,
"default": 10
}
},
"required": [],
"visible": ["limit"]
},
"body": {
"type": "object",
"properties": {
"origin": {
"type": "string",
"description": "Origin airport code",
"pattern": "^[A-Z]{3}$"
},
"destination": {
"type": "string",
"description": "Destination airport code",
"pattern": "^[A-Z]{3}$"
},
"date": {
"type": "string",
"format": "date",
"description": "Departure date"
}
},
"required": ["origin", "destination", "date"],
"visible": ["origin", "destination", "date"]
}
},
"metadata": {
"source": "openapi",
"confidence": 0.95
}
}
工具命名约定
工具遵循以下模式: VENDOR__RESOURCE__VERB (大写)
示例:
STRIPE__PAYMENTS__CREATEGITHUB__REPOSITORIES__LISTEXAMPLE__BOOKINGS__DELETE
字段描述
| 字段 | 类型 | 描述 |
|---|---|---|
name |
string | 唯一工具标识符(VENDOR__RESOURCE__VERB) |
display_name |
string | UI显示的人类可读名称 |
description |
string | 工具功能的清晰描述 |
tags |
array | [供应商、资源、版本、方法] |
visibility |
string | 始终为“public” |
active |
boolean | 始终为真 |
protocol |
string | 总是“休息” |
protocol_data |
object | 包含方法、路径和server_url |
parameters |
object | 头/路径/查询/正文的嵌套架构 |
metadata |
object | 源类型和置信度得分 |
发展
运行测试
# Run full workflow test
uv run python tests/test_workflow.py
# Run with example data
uv run python main.py --example
代码质量
该项目使用 拉夫 用于代码格式化、导入排序和linting。
# Format code
uv run ruff format .
# Sort imports and fix issues
uv run ruff check --fix .
# Lint code (check only)
uv run ruff check .
重要实施注意事项
-
Pydantic版本兼容性:
- 使用
from pydantic import BaseModel, Field(Pydantic v2) - 请勿使用已弃用的
langchain_core.pydantic_v1导入
- 使用
-
Azure OpenAI:
- 此项目使用Azure OpenAI,而不是标准OpenAI
- 配置所有必需的Azure环境变量
-
自定义架构字段:
- 这
visible字段是UI渲染的自定义扩展名 - 在JSON模式验证过程中会自动删除它
- 这
-
检查点:
- 默认情况下使用内存中的SQLite
- 可以更改为基于文件的
utils/workflow.py
-
类型提示:
- 所有函数都包含全面的类型提示
- 使用Python
typing整个模块
依赖项
关键包(见 pyproject.toml 完整列表):
工作流和LLM
langgraph>=1.0.1-工作流编排langchain>=1.0.2-LLM运营langchain-openai>=1.0.1-Azure OpenAI集成langgraph-checkpoint-sqlite>=3.0.0-状态持久性
CLI和实用程序
click>=8.1.0-现代CLI框架python-dotenv-环境变量管理
数据处理
beautifulsoup4>=4.14.2-用于web发现的HTML/XML解析jsonschema>=4.25.1-架构验证pyyaml>=6.0.3-YAML解析requests>=2.32.5-HTTP请求
开发工具
ruff>=0.14.3-代码格式化、导入排序和linting
学习资源
许可证
这是一个用于教育和参考目的的演示项目。请根据您的具体使用情况进行调整。
贡献
这是一个演示存储库。如有疑问或建议,请打开一个问题。
免责声明
此存储库仅用于演示目的。 它展示了使用LangGraph的工作流编排模式,应该针对生产用例进行调整和强化。该代码演示了架构概念,可能需要额外的错误处理、安全考虑和实际应用程序的性能优化。
