yapi-mcp 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl
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.
- yapi_mcp/__init__.py +5 -0
- yapi_mcp/__main__.py +6 -0
- config.py → yapi_mcp/config.py +48 -48
- yapi_mcp/server.py +185 -0
- {tools → yapi_mcp/tools}/__init__.py +1 -1
- {yapi → yapi_mcp/yapi}/__init__.py +1 -1
- yapi_mcp/yapi/client.py +259 -0
- {yapi → yapi_mcp/yapi}/errors.py +43 -21
- {yapi → yapi_mcp/yapi}/models.py +61 -60
- yapi_mcp-0.1.2.dist-info/METADATA +174 -0
- yapi_mcp-0.1.2.dist-info/RECORD +14 -0
- {yapi_mcp-0.1.0.dist-info → yapi_mcp-0.1.2.dist-info}/WHEEL +1 -1
- yapi_mcp-0.1.2.dist-info/entry_points.txt +2 -0
- {yapi_mcp-0.1.0.dist-info → yapi_mcp-0.1.2.dist-info}/licenses/LICENSE +21 -21
- __init__.py +0 -1
- server.py +0 -148
- yapi/client.py +0 -206
- yapi_mcp-0.1.0.dist-info/METADATA +0 -394
- yapi_mcp-0.1.0.dist-info/RECORD +0 -13
- yapi_mcp-0.1.0.dist-info/entry_points.txt +0 -2
{yapi → yapi_mcp/yapi}/models.py
RENAMED
|
@@ -1,60 +1,61 @@
|
|
|
1
|
-
"""Pydantic models for YApi API data structures."""
|
|
2
|
-
|
|
3
|
-
from typing import Literal
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class YApiInterface(BaseModel):
|
|
9
|
-
"""YApi interface complete definition from API responses."""
|
|
10
|
-
|
|
11
|
-
model_config = ConfigDict(populate_by_name=True)
|
|
12
|
-
|
|
13
|
-
id: int = Field(..., alias="_id", description="Interface ID")
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
"""Pydantic models for YApi API data structures."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class YApiInterface(BaseModel):
|
|
9
|
+
"""YApi interface complete definition from API responses."""
|
|
10
|
+
|
|
11
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
12
|
+
|
|
13
|
+
id: int = Field(..., alias="_id", description="Interface ID")
|
|
14
|
+
catid: int = Field(..., description="Category ID this interface belongs to")
|
|
15
|
+
title: str = Field(..., description="Interface title")
|
|
16
|
+
path: str = Field(..., description="Interface path", examples=["/api/user/login"])
|
|
17
|
+
|
|
18
|
+
method: Literal["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"] = Field(
|
|
19
|
+
...,
|
|
20
|
+
description="HTTP method",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
project_id: int = Field(..., description="Project ID this interface belongs to")
|
|
24
|
+
|
|
25
|
+
desc: str | None = Field(None, description="Interface description")
|
|
26
|
+
req_body_other: str | None = Field(
|
|
27
|
+
None, description="Request parameters definition (JSON string)"
|
|
28
|
+
)
|
|
29
|
+
res_body: str | None = Field(None, description="Response structure definition (JSON string)")
|
|
30
|
+
status: str | None = Field(None, description="Status code")
|
|
31
|
+
|
|
32
|
+
add_time: int | None = Field(None, description="Creation timestamp (Unix epoch)")
|
|
33
|
+
up_time: int | None = Field(None, description="Last update timestamp (Unix epoch)")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class YApiInterfaceSummary(BaseModel):
|
|
37
|
+
"""YApi interface summary from search results."""
|
|
38
|
+
|
|
39
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
40
|
+
|
|
41
|
+
id: int = Field(..., alias="_id", description="Interface ID")
|
|
42
|
+
title: str = Field(..., description="Interface title")
|
|
43
|
+
path: str = Field(..., description="Interface path")
|
|
44
|
+
method: str = Field(..., description="HTTP method")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class YApiErrorResponse(BaseModel):
|
|
48
|
+
"""YApi API error response structure."""
|
|
49
|
+
|
|
50
|
+
errcode: int = Field(..., description="Error code (non-zero indicates error)")
|
|
51
|
+
errmsg: str = Field(..., description="Error message")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class YApiProject(BaseModel):
|
|
55
|
+
"""YApi project information (optional, for future use)."""
|
|
56
|
+
|
|
57
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
58
|
+
|
|
59
|
+
id: int = Field(..., alias="_id", description="Project ID")
|
|
60
|
+
name: str = Field(..., description="Project name")
|
|
61
|
+
desc: str | None = Field(None, description="Project description")
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yapi-mcp
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Model Context Protocol server for YApi 1.12.0 API management platform
|
|
5
|
+
Project-URL: Homepage, https://github.com/geq1fan/yapi-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/geq1fan/yapi-mcp
|
|
7
|
+
Project-URL: Issues, https://github.com/geq1fan/yapi-mcp/issues
|
|
8
|
+
Author: YApi MCP Team
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: api,fastmcp,mcp,model-context-protocol,yapi
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: fastmcp>=2.0.0
|
|
22
|
+
Requires-Dist: httpx>=0.27.0
|
|
23
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: respx>=0.21.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# YApi MCP Server
|
|
32
|
+
|
|
33
|
+
[](https://www.python.org/downloads/)
|
|
34
|
+
[](LICENSE)
|
|
35
|
+
[](https://github.com/astral-sh/ruff)
|
|
36
|
+
|
|
37
|
+
基于 [YApi 1.12.0](https://github.com/YMFE/yapi) 接口管理平台的 Model Context Protocol (MCP) 服务器。
|
|
38
|
+
|
|
39
|
+
使开发者能够在支持 MCP 的 IDE 和编辑器(Claude Code、Cursor 等)中直接搜索、查看、创建和更新 YApi 接口定义,无需离开开发环境。
|
|
40
|
+
|
|
41
|
+
## 功能特性
|
|
42
|
+
|
|
43
|
+
- 🔍 **搜索接口**: 通过标题、路径或描述查找 API 端点
|
|
44
|
+
- 📖 **查看定义**: 获取完整的接口规范,包括请求/响应结构
|
|
45
|
+
- ➕ **创建接口**: 向 YApi 项目添加新的 API 定义
|
|
46
|
+
- ✏️ **更新接口**: 修改现有接口配置
|
|
47
|
+
- 🔐 **Cookie 认证**: 基于会话的安全认证
|
|
48
|
+
- ⚡ **异步性能**: 基于 httpx 实现高效的并发操作
|
|
49
|
+
|
|
50
|
+
## 环境要求
|
|
51
|
+
|
|
52
|
+
- Python 3.11 或更高版本
|
|
53
|
+
- YApi 1.12.0 实例(可通过 HTTP/HTTPS 访问)
|
|
54
|
+
- 有效的 YApi 认证 cookies
|
|
55
|
+
|
|
56
|
+
## 配置
|
|
57
|
+
|
|
58
|
+
### 1. 获取 YApi Cookies
|
|
59
|
+
|
|
60
|
+
1. 在浏览器中登录 YApi 实例
|
|
61
|
+
2. 打开开发者工具(F12)
|
|
62
|
+
3. 导航到 **Application** → **Cookies**(Chrome) 或 **Storage** → **Cookies**(Firefox)
|
|
63
|
+
4. 复制以下 cookie 值:
|
|
64
|
+
- `_yapi_token` (必需)
|
|
65
|
+
- `_yapi_uid` (必需)
|
|
66
|
+
- `ZYBIPSCAS` (可选,仅某些自定义部署需要)
|
|
67
|
+
|
|
68
|
+
### 2. 配置 MCP
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"yapi": {
|
|
74
|
+
"command": "uvx",
|
|
75
|
+
"args": ["--from", "/path/to/yapi-mcp", "yapi-mcp"],
|
|
76
|
+
"env": {
|
|
77
|
+
"YAPI_SERVER_URL": "https://your-yapi-instance.com",
|
|
78
|
+
"YAPI_TOKEN": "your_token",
|
|
79
|
+
"YAPI_UID": "your_uid"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> **注意**: 如果你的 YApi 部署需要额外的 CAS 认证,添加 `"YAPI_CAS": "your_cas_value"` 到 `env` 中。
|
|
87
|
+
|
|
88
|
+
## 开发
|
|
89
|
+
|
|
90
|
+
### 运行测试
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# 安装开发依赖
|
|
94
|
+
pip install -e ".[dev]"
|
|
95
|
+
|
|
96
|
+
# 运行所有测试
|
|
97
|
+
pytest
|
|
98
|
+
|
|
99
|
+
# 运行并显示覆盖率
|
|
100
|
+
pytest --cov=src --cov-report=term-missing
|
|
101
|
+
|
|
102
|
+
# 运行特定测试文件
|
|
103
|
+
pytest tests/test_config.py
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 代码质量
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# 格式化代码
|
|
110
|
+
ruff format
|
|
111
|
+
|
|
112
|
+
# 代码检查
|
|
113
|
+
ruff check
|
|
114
|
+
|
|
115
|
+
# 自动修复检查问题
|
|
116
|
+
ruff check --fix
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 项目结构
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
yapi-mcp/
|
|
123
|
+
├── src/
|
|
124
|
+
│ ├── server.py # MCP 服务器入口点
|
|
125
|
+
│ ├── config.py # 配置模型
|
|
126
|
+
│ ├── yapi/
|
|
127
|
+
│ │ ├── client.py # YApi API 客户端
|
|
128
|
+
│ │ ├── models.py # Pydantic 数据模型
|
|
129
|
+
│ │ └── errors.py # 错误映射
|
|
130
|
+
│ └── tools/ # MCP 工具(在 server.py 中注册)
|
|
131
|
+
├── tests/ # 测试套件
|
|
132
|
+
├── specs/ # 设计文档
|
|
133
|
+
├── pyproject.toml # 项目配置
|
|
134
|
+
├── .env.example # 环境变量模板
|
|
135
|
+
└── README.md # 本文件
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 贡献
|
|
139
|
+
|
|
140
|
+
欢迎贡献! 我们非常感谢各种形式的贡献,包括但不限于:
|
|
141
|
+
|
|
142
|
+
- 🐛 报告 Bug
|
|
143
|
+
- ✨ 建议新功能
|
|
144
|
+
- 📝 改进文档
|
|
145
|
+
- 💻 提交代码
|
|
146
|
+
|
|
147
|
+
在开始贡献之前,请阅读我们的[贡献指南](CONTRIBUTING.md)。
|
|
148
|
+
|
|
149
|
+
### 快速开始
|
|
150
|
+
|
|
151
|
+
1. Fork 本仓库
|
|
152
|
+
2. 创建功能分支 (`git checkout -b feature/amazing-feature`)
|
|
153
|
+
3. 提交更改 (`git commit -m 'feat: 添加惊人的功能'`)
|
|
154
|
+
4. 推送到分支 (`git push origin feature/amazing-feature`)
|
|
155
|
+
5. 创建 Pull Request
|
|
156
|
+
|
|
157
|
+
### 代码质量要求
|
|
158
|
+
|
|
159
|
+
- ✅ 所有测试通过: `pytest`
|
|
160
|
+
- ✅ 代码已格式化: `ruff format`
|
|
161
|
+
- ✅ 无检查错误: `ruff check`
|
|
162
|
+
- ✅ 新功能包含测试
|
|
163
|
+
|
|
164
|
+
详细信息请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
|
165
|
+
|
|
166
|
+
## 许可证
|
|
167
|
+
|
|
168
|
+
本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。
|
|
169
|
+
|
|
170
|
+
## 相关项目
|
|
171
|
+
|
|
172
|
+
- [YApi](https://github.com/YMFE/yapi) - API 管理平台
|
|
173
|
+
- [fastmcp](https://github.com/jlowin/fastmcp) - Python MCP 框架
|
|
174
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/) - MCP 规范
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
yapi_mcp/__init__.py,sha256=-B1Yt-BsgzhccXKx5Y6f3TWR1OQbb8I8cOvnSKYjcSU,136
|
|
2
|
+
yapi_mcp/__main__.py,sha256=hOOyTtbTkoNugBbb_SofxEMRf8PuoOhWa8Z8-OyfWqw,151
|
|
3
|
+
yapi_mcp/config.py,sha256=k19HWCCBfBJttlsWj4f2QdxvFoBvHSJ1AVvb08WT-tQ,1373
|
|
4
|
+
yapi_mcp/server.py,sha256=NVkl_PKBzDjBbjyl2ynpxtf8cpKRtaWz9H0BZ6UDxpQ,6564
|
|
5
|
+
yapi_mcp/tools/__init__.py,sha256=iCyxPtAUoQ7RU976LPMXgGghqm2l0bH-LYBCnEOLtew,33
|
|
6
|
+
yapi_mcp/yapi/__init__.py,sha256=gK6ta7uNWkDqen5yWSDqqXYlCxz3uU-A2bKaqeO55Qk,31
|
|
7
|
+
yapi_mcp/yapi/client.py,sha256=gcwYdeHT9Yjq-550HyDh61wJYS8TeeAgFMoXoeb-bIg,10058
|
|
8
|
+
yapi_mcp/yapi/errors.py,sha256=RQvvdl1d-CBawZDTdgf3g_ThJUhGUvwRPCI-q2I6Mfc,3815
|
|
9
|
+
yapi_mcp/yapi/models.py,sha256=MJZQx_esXPcQ7UTnhlo_QVU81NrIPF2pB36mxvcLJ5w,2349
|
|
10
|
+
yapi_mcp-0.1.2.dist-info/METADATA,sha256=NpaST-JZA4syzU8qEK9A0LrcgVmmNogsuksUdYRr3Wo,5198
|
|
11
|
+
yapi_mcp-0.1.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
12
|
+
yapi_mcp-0.1.2.dist-info/entry_points.txt,sha256=u1QWnfoawIuUR6RuyPmqi9TpySnasIRU1lvJZa315EU,43
|
|
13
|
+
yapi_mcp-0.1.2.dist-info/licenses/LICENSE,sha256=b-a1jI555eCf0fkRmK3mrIGQe8hYqC5aXy0nGXiEasA,1106
|
|
14
|
+
yapi_mcp-0.1.2.dist-info/RECORD,,
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 YApi MCP Server Contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 YApi MCP Server Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""YApi MCP Server - Model Context Protocol adapter for YApi."""
|
server.py
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
"""YApi MCP Server - Main server module with fastmcp."""
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
from typing import Annotated
|
|
5
|
-
|
|
6
|
-
import httpx
|
|
7
|
-
from fastmcp import FastMCP
|
|
8
|
-
|
|
9
|
-
from config import ServerConfig
|
|
10
|
-
from yapi.client import YApiClient
|
|
11
|
-
from yapi.errors import map_http_error_to_mcp
|
|
12
|
-
|
|
13
|
-
# Initialize MCP server
|
|
14
|
-
mcp = FastMCP(
|
|
15
|
-
"YApi MCP Server",
|
|
16
|
-
version="0.1.0",
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def get_config() -> ServerConfig:
|
|
21
|
-
"""Get or create ServerConfig instance (lazy loading)."""
|
|
22
|
-
if not hasattr(get_config, "_instance"):
|
|
23
|
-
get_config._instance = ServerConfig()
|
|
24
|
-
return get_config._instance
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# Tool implementations will be added in subsequent tasks (T019-T022)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@mcp.tool()
|
|
31
|
-
async def yapi_search_interfaces(
|
|
32
|
-
project_id: Annotated[int, "YApi 项目 ID"],
|
|
33
|
-
keyword: Annotated[str, "搜索关键词(匹配接口标题/路径/描述)"],
|
|
34
|
-
) -> str:
|
|
35
|
-
"""在指定 YApi 项目中搜索接口,支持按标题、路径、描述模糊匹配."""
|
|
36
|
-
config = get_config()
|
|
37
|
-
try:
|
|
38
|
-
async with YApiClient(str(config.yapi_server_url), config.cookies) as client:
|
|
39
|
-
results = await client.search_interfaces(project_id, keyword)
|
|
40
|
-
# Return JSON string with search results
|
|
41
|
-
return json.dumps(
|
|
42
|
-
[result.model_dump(by_alias=True) for result in results],
|
|
43
|
-
ensure_ascii=False,
|
|
44
|
-
indent=2,
|
|
45
|
-
)
|
|
46
|
-
except httpx.HTTPStatusError as e:
|
|
47
|
-
mcp_error = map_http_error_to_mcp(e)
|
|
48
|
-
raise Exception(mcp_error.message) from e
|
|
49
|
-
except Exception as e:
|
|
50
|
-
raise Exception(f"搜索接口失败: {e!s}") from e
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@mcp.tool()
|
|
54
|
-
async def yapi_get_interface(
|
|
55
|
-
interface_id: Annotated[int, "接口 ID"],
|
|
56
|
-
) -> str:
|
|
57
|
-
"""获取 YApi 接口的完整定义(包括请求参数、响应结构、描述等)."""
|
|
58
|
-
config = get_config()
|
|
59
|
-
try:
|
|
60
|
-
async with YApiClient(str(config.yapi_server_url), config.cookies) as client:
|
|
61
|
-
interface = await client.get_interface(interface_id)
|
|
62
|
-
return json.dumps(
|
|
63
|
-
interface.model_dump(by_alias=True),
|
|
64
|
-
ensure_ascii=False,
|
|
65
|
-
indent=2,
|
|
66
|
-
)
|
|
67
|
-
except httpx.HTTPStatusError as e:
|
|
68
|
-
mcp_error = map_http_error_to_mcp(e)
|
|
69
|
-
raise Exception(mcp_error.message) from e
|
|
70
|
-
except Exception as e:
|
|
71
|
-
raise Exception(f"获取接口失败: {e!s}") from e
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
@mcp.tool()
|
|
75
|
-
async def yapi_create_interface(
|
|
76
|
-
project_id: Annotated[int, "项目 ID"],
|
|
77
|
-
title: Annotated[str, "接口标题"],
|
|
78
|
-
path: Annotated[str, "接口路径(以 / 开头)"],
|
|
79
|
-
method: Annotated[str, "HTTP 方法(GET/POST/PUT/DELETE等)"],
|
|
80
|
-
req_body: Annotated[str, "请求参数(JSON 字符串,可选)"] = "",
|
|
81
|
-
res_body: Annotated[str, "响应结构(JSON 字符串,可选)"] = "",
|
|
82
|
-
desc: Annotated[str, "接口描述(可选)"] = "",
|
|
83
|
-
) -> str:
|
|
84
|
-
"""在 YApi 项目中创建新接口定义."""
|
|
85
|
-
config = get_config()
|
|
86
|
-
try:
|
|
87
|
-
# Validate path starts with /
|
|
88
|
-
if not path.startswith("/"):
|
|
89
|
-
raise ValueError("接口路径必须以 / 开头")
|
|
90
|
-
|
|
91
|
-
async with YApiClient(str(config.yapi_server_url), config.cookies) as client:
|
|
92
|
-
interface_id = await client.create_interface(
|
|
93
|
-
project_id, title, path, method, req_body, res_body, desc
|
|
94
|
-
)
|
|
95
|
-
return json.dumps(
|
|
96
|
-
{"interface_id": interface_id},
|
|
97
|
-
ensure_ascii=False,
|
|
98
|
-
)
|
|
99
|
-
except httpx.HTTPStatusError as e:
|
|
100
|
-
mcp_error = map_http_error_to_mcp(e)
|
|
101
|
-
raise Exception(mcp_error.message) from e
|
|
102
|
-
except ValueError as e:
|
|
103
|
-
raise Exception(f"参数验证失败: {e!s}") from e
|
|
104
|
-
except Exception as e:
|
|
105
|
-
raise Exception(f"创建接口失败: {e!s}") from e
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@mcp.tool()
|
|
109
|
-
async def yapi_update_interface(
|
|
110
|
-
interface_id: Annotated[int, "接口 ID"],
|
|
111
|
-
title: Annotated[str | None, "更新的标题"] = None,
|
|
112
|
-
path: Annotated[str | None, "更新的路径"] = None,
|
|
113
|
-
method: Annotated[str | None, "更新的 HTTP 方法"] = None,
|
|
114
|
-
req_body: Annotated[str | None, "更新的请求参数"] = None,
|
|
115
|
-
res_body: Annotated[str | None, "更新的响应结构"] = None,
|
|
116
|
-
desc: Annotated[str | None, "更新的描述"] = None,
|
|
117
|
-
) -> str:
|
|
118
|
-
"""增量更新 YApi 接口定义(仅更新提供的字段)."""
|
|
119
|
-
config = get_config()
|
|
120
|
-
try:
|
|
121
|
-
# Validate path if provided
|
|
122
|
-
if path is not None and not path.startswith("/"):
|
|
123
|
-
raise ValueError("接口路径必须以 / 开头")
|
|
124
|
-
|
|
125
|
-
async with YApiClient(str(config.yapi_server_url), config.cookies) as client:
|
|
126
|
-
success = await client.update_interface(
|
|
127
|
-
interface_id, title, path, method, req_body, res_body, desc
|
|
128
|
-
)
|
|
129
|
-
return json.dumps(
|
|
130
|
-
{"success": success, "message": "接口更新成功"},
|
|
131
|
-
ensure_ascii=False,
|
|
132
|
-
)
|
|
133
|
-
except httpx.HTTPStatusError as e:
|
|
134
|
-
mcp_error = map_http_error_to_mcp(e)
|
|
135
|
-
raise Exception(mcp_error.message) from e
|
|
136
|
-
except ValueError as e:
|
|
137
|
-
raise Exception(f"参数验证失败: {e!s}") from e
|
|
138
|
-
except Exception as e:
|
|
139
|
-
raise Exception(f"更新接口失败: {e!s}") from e
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def main() -> None:
|
|
143
|
-
"""Entry point for uvx yapi-mcp command."""
|
|
144
|
-
mcp.run()
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if __name__ == "__main__":
|
|
148
|
-
main()
|