kibana-reader-mcp 0.1.0__tar.gz

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.
@@ -0,0 +1,71 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class*
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # PyInstaller
28
+ *.manifest
29
+ *.spec
30
+
31
+ # Installer logs
32
+ pip-log.txt
33
+ pip-delete-this-directory.txt
34
+
35
+ # Unit test / coverage reports
36
+ htmlcov/
37
+ .tox/
38
+ .nox/
39
+ .coverage
40
+ .coverage.*
41
+ .cache
42
+ nosetests.xml
43
+ coverage.xml
44
+ *.cover
45
+ *.py,cover
46
+ .hypothesis/
47
+ .pytest_cache/
48
+
49
+ # Translations
50
+ *.mo
51
+ *.pot
52
+
53
+ # Environments
54
+ .env
55
+ .venv
56
+ env/
57
+ venv/
58
+ ENV/
59
+ env.bak/
60
+ venv.bak/
61
+
62
+ # IDE
63
+ .idea/
64
+ .vscode/
65
+ *.swp
66
+ *.swo
67
+
68
+ # Session files
69
+ session.json
70
+ config.json
71
+ .claude/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 yuyangfan
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.
@@ -0,0 +1,155 @@
1
+ Metadata-Version: 2.4
2
+ Name: kibana-reader-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for reading Kibana pages with DingTalk scan login
5
+ Project-URL: Homepage, https://gitee.com/yuyangfan/kibana-reader-mcp
6
+ Project-URL: Repository, https://gitee.com/yuyangfan/kibana-reader-mcp
7
+ Project-URL: Documentation, https://gitee.com/yuyangfan/kibana-reader-mcp#readme
8
+ Author-email: yuyangfan <yuyangfan@example.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: elasticsearch,kibana,logs,mcp,model-context-protocol
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.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: httpx>=0.27.0
22
+ Requires-Dist: mcp>=1.0.0
23
+ Requires-Dist: playwright>=1.40.0
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: build>=1.0.0; extra == 'dev'
27
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
28
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
29
+ Requires-Dist: twine>=5.0.0; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Kibana Reader MCP
33
+
34
+ 一个用于读取 Kibana 页面内容的 MCP Server,支持钉钉扫码登录。
35
+
36
+ ## 功能
37
+
38
+ - 读取 Kibana Discover 页面数据
39
+ - 读取 Kibana Dashboard 页面数据
40
+ - 支持短 URL 自动重定向
41
+ - 自动管理 Cookie/Session
42
+ - 支持钉钉扫码认证
43
+
44
+ ## 安装
45
+
46
+ ```bash
47
+ pip install kibana-reader-mcp
48
+ playwright install chromium
49
+ ```
50
+
51
+ ## 配置
52
+
53
+ ### 方式一:配置文件
54
+
55
+ 创建配置文件 `~/.kibana-reader-mcp/config.json`:
56
+
57
+ ```json
58
+ {
59
+ "kibana_base_url": "https://your-kibana.example.com",
60
+ "session_file": "~/.kibana-reader-mcp/session.json",
61
+ "playwright_headless": false,
62
+ "scan_timeout_seconds": 120,
63
+ "default_max_rows": 100
64
+ }
65
+ ```
66
+
67
+ ### 方式二:环境变量
68
+
69
+ ```bash
70
+ export KIBANA_BASE_URL="https://your-kibana.example.com"
71
+ export PLAYWRIGHT_HEADLESS=false
72
+ export SCAN_TIMEOUT_SECONDS=120
73
+ ```
74
+
75
+ ## 客户端配置
76
+
77
+ ### Claude Desktop
78
+
79
+ 编辑 `~/Library/Application Support/Claude/claude_desktop_config.json`:
80
+
81
+ ```json
82
+ {
83
+ "mcpServers": {
84
+ "kibana-reader": {
85
+ "command": "uvx",
86
+ "args": ["kibana-reader-mcp"],
87
+ "env": {
88
+ "KIBANA_BASE_URL": "https://your-kibana.example.com"
89
+ }
90
+ }
91
+ }
92
+ }
93
+ ```
94
+
95
+ ### Claude Code
96
+
97
+ 编辑 `~/.claude/settings.json`:
98
+
99
+ ```json
100
+ {
101
+ "mcpServers": {
102
+ "kibana-reader": {
103
+ "command": "uvx",
104
+ "args": ["kibana-reader-mcp"],
105
+ "env": {
106
+ "KIBANA_BASE_URL": "https://your-kibana.example.com"
107
+ }
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### Cursor / Windsurf / Codex
114
+
115
+ 在 MCP 设置中添加服务器配置,格式同上。
116
+
117
+ ## 使用示例
118
+
119
+ ```
120
+ AI: 调用 read_kibana_url
121
+ 参数:
122
+ - url: "https://your-kibana/goto/abc123"
123
+ - max_rows: 100
124
+
125
+ 返回: Kibana 页面的结构化数据
126
+ ```
127
+
128
+ ## 认证流程
129
+
130
+ 1. 首次使用时,MCP 会打开浏览器显示钉钉扫码页面
131
+ 2. 用户扫码登录后,MCP 自动保存 Cookie
132
+ 3. 后续调用直接使用保存的 Cookie
133
+ 4. Cookie 过期时自动提示重新扫码
134
+
135
+ ## URL 类型支持
136
+
137
+ | 类型 | 示例 | 处理方式 |
138
+ |------|------|---------|
139
+ | 短 URL | `/goto/abc123` | Playwright 重定向 |
140
+ | Discover | `/app/kibana#/discover` | API 调用 |
141
+ | Dashboard | `/app/kibana#/dashboard` | API 调用 |
142
+
143
+ ## 开发
144
+
145
+ ```bash
146
+ # 安装开发依赖
147
+ pip install -e ".[dev]"
148
+
149
+ # 运行测试
150
+ pytest
151
+ ```
152
+
153
+ ## License
154
+
155
+ MIT
@@ -0,0 +1,124 @@
1
+ # Kibana Reader MCP
2
+
3
+ 一个用于读取 Kibana 页面内容的 MCP Server,支持钉钉扫码登录。
4
+
5
+ ## 功能
6
+
7
+ - 读取 Kibana Discover 页面数据
8
+ - 读取 Kibana Dashboard 页面数据
9
+ - 支持短 URL 自动重定向
10
+ - 自动管理 Cookie/Session
11
+ - 支持钉钉扫码认证
12
+
13
+ ## 安装
14
+
15
+ ```bash
16
+ pip install kibana-reader-mcp
17
+ playwright install chromium
18
+ ```
19
+
20
+ ## 配置
21
+
22
+ ### 方式一:配置文件
23
+
24
+ 创建配置文件 `~/.kibana-reader-mcp/config.json`:
25
+
26
+ ```json
27
+ {
28
+ "kibana_base_url": "https://your-kibana.example.com",
29
+ "session_file": "~/.kibana-reader-mcp/session.json",
30
+ "playwright_headless": false,
31
+ "scan_timeout_seconds": 120,
32
+ "default_max_rows": 100
33
+ }
34
+ ```
35
+
36
+ ### 方式二:环境变量
37
+
38
+ ```bash
39
+ export KIBANA_BASE_URL="https://your-kibana.example.com"
40
+ export PLAYWRIGHT_HEADLESS=false
41
+ export SCAN_TIMEOUT_SECONDS=120
42
+ ```
43
+
44
+ ## 客户端配置
45
+
46
+ ### Claude Desktop
47
+
48
+ 编辑 `~/Library/Application Support/Claude/claude_desktop_config.json`:
49
+
50
+ ```json
51
+ {
52
+ "mcpServers": {
53
+ "kibana-reader": {
54
+ "command": "uvx",
55
+ "args": ["kibana-reader-mcp"],
56
+ "env": {
57
+ "KIBANA_BASE_URL": "https://your-kibana.example.com"
58
+ }
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
64
+ ### Claude Code
65
+
66
+ 编辑 `~/.claude/settings.json`:
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "kibana-reader": {
72
+ "command": "uvx",
73
+ "args": ["kibana-reader-mcp"],
74
+ "env": {
75
+ "KIBANA_BASE_URL": "https://your-kibana.example.com"
76
+ }
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Cursor / Windsurf / Codex
83
+
84
+ 在 MCP 设置中添加服务器配置,格式同上。
85
+
86
+ ## 使用示例
87
+
88
+ ```
89
+ AI: 调用 read_kibana_url
90
+ 参数:
91
+ - url: "https://your-kibana/goto/abc123"
92
+ - max_rows: 100
93
+
94
+ 返回: Kibana 页面的结构化数据
95
+ ```
96
+
97
+ ## 认证流程
98
+
99
+ 1. 首次使用时,MCP 会打开浏览器显示钉钉扫码页面
100
+ 2. 用户扫码登录后,MCP 自动保存 Cookie
101
+ 3. 后续调用直接使用保存的 Cookie
102
+ 4. Cookie 过期时自动提示重新扫码
103
+
104
+ ## URL 类型支持
105
+
106
+ | 类型 | 示例 | 处理方式 |
107
+ |------|------|---------|
108
+ | 短 URL | `/goto/abc123` | Playwright 重定向 |
109
+ | Discover | `/app/kibana#/discover` | API 调用 |
110
+ | Dashboard | `/app/kibana#/dashboard` | API 调用 |
111
+
112
+ ## 开发
113
+
114
+ ```bash
115
+ # 安装开发依赖
116
+ pip install -e ".[dev]"
117
+
118
+ # 运行测试
119
+ pytest
120
+ ```
121
+
122
+ ## License
123
+
124
+ MIT
@@ -0,0 +1,62 @@
1
+ [project]
2
+ name = "kibana-reader-mcp"
3
+ version = "0.1.0"
4
+ description = "MCP server for reading Kibana pages with DingTalk scan login"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ requires-python = ">=3.10"
8
+ authors = [
9
+ { name = "yuyangfan", email = "yuyangfan@example.com" }
10
+ ]
11
+ keywords = ["mcp", "kibana", "elasticsearch", "logs", "model-context-protocol"]
12
+ classifiers = [
13
+ "Development Status :: 4 - Beta",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ ]
22
+ dependencies = [
23
+ "mcp>=1.0.0",
24
+ "playwright>=1.40.0",
25
+ "httpx>=0.27.0",
26
+ "pydantic>=2.0.0",
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ dev = [
31
+ "pytest>=8.0.0",
32
+ "pytest-asyncio>=0.23.0",
33
+ "build>=1.0.0",
34
+ "twine>=5.0.0",
35
+ ]
36
+
37
+ [project.scripts]
38
+ kibana-reader-mcp = "kibana_reader_mcp.server:run"
39
+
40
+ [project.urls]
41
+ Homepage = "https://gitee.com/yuyangfan/kibana-reader-mcp"
42
+ Repository = "https://gitee.com/yuyangfan/kibana-reader-mcp"
43
+ Documentation = "https://gitee.com/yuyangfan/kibana-reader-mcp#readme"
44
+
45
+ [build-system]
46
+ requires = ["hatchling"]
47
+ build-backend = "hatchling.build"
48
+
49
+ [tool.hatch.build.targets.wheel]
50
+ packages = ["src/kibana_reader_mcp"]
51
+
52
+ [tool.hatch.build.targets.sdist]
53
+ include = [
54
+ "src/kibana_reader_mcp/",
55
+ "README.md",
56
+ "LICENSE",
57
+ "pyproject.toml",
58
+ ]
59
+
60
+ [tool.pytest.ini_options]
61
+ asyncio_mode = "auto"
62
+ testpaths = ["tests"]
@@ -0,0 +1,3 @@
1
+ """Kibana Reader MCP - A MCP server for reading Kibana page content."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+ """Entry point for running the MCP server via python -m kibana_reader_mcp."""
2
+
3
+ from .server import run
4
+
5
+ if __name__ == "__main__":
6
+ run()
@@ -0,0 +1,196 @@
1
+ """Authentication management for Kibana with DingTalk scan login."""
2
+
3
+ import json
4
+ import time
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
8
+ import httpx
9
+ from playwright.async_api import async_playwright, Browser, Page
10
+
11
+ from .config import Config, get_session_path, ensure_config_dir
12
+
13
+
14
+ class SessionData:
15
+ """Session 数据模型"""
16
+
17
+ cookies: dict
18
+ created_at: float
19
+ expires_at: Optional[float] = None
20
+
21
+ def __init__(self, cookies: dict, created_at: float = None):
22
+ self.cookies = cookies
23
+ self.created_at = created_at or time.time()
24
+ self.expires_at = None
25
+
26
+ def is_expired(self, max_age_seconds: int = 3600 *24) -> bool:
27
+ """检查 Session 是否过期"""
28
+ if self.expires_at:
29
+ return time.time() > self.expires_at
30
+ # 默认24小时过期
31
+ return time.time() > self.created_at + max_age_seconds
32
+
33
+ def to_dict(self) -> dict:
34
+ return {
35
+ "cookies": self.cookies,
36
+ "created_at": self.created_at,
37
+ "expires_at": self.expires_at,
38
+ }
39
+
40
+ @classmethod
41
+ def from_dict(cls, data: dict) -> "SessionData":
42
+ return cls(
43
+ cookies=data.get("cookies", {}),
44
+ created_at=data.get("created_at"),
45
+ )
46
+
47
+
48
+ class AuthManager:
49
+ """认证管理器"""
50
+
51
+ def __init__(self, config: Config):
52
+ self.config = config
53
+ self.session: Optional[SessionData] = None
54
+ self._browser: Optional[Browser] = None
55
+
56
+ def load_session(self) -> Optional[SessionData]:
57
+ """从文件加载 Session"""
58
+ session_path = get_session_path(self.config)
59
+
60
+ if session_path.exists():
61
+ try:
62
+ with open(session_path, "r") as f:
63
+ data = json.load(f)
64
+ self.session = SessionData.from_dict(data)
65
+ return self.session
66
+ except Exception:
67
+ return None
68
+ return None
69
+
70
+ def save_session(self):
71
+ """保存 Session 到文件"""
72
+ ensure_config_dir()
73
+ session_path = get_session_path(self.config)
74
+
75
+ if self.session:
76
+ with open(session_path, "w") as f:
77
+ json.dump(self.session.to_dict(), f)
78
+
79
+ async def ensure_authenticated(self) -> dict:
80
+ """确保已认证,返回有效的 cookies"""
81
+ # 检查是否有有效 Session
82
+ if self.session and not self.session.is_expired():
83
+ return self.session.cookies
84
+
85
+ # 尝试加载已保存的 Session
86
+ loaded = self.load_session()
87
+ if loaded and not loaded.is_expired():
88
+ self.session = loaded
89
+ return self.session.cookies
90
+
91
+ # 需要重新登录(扫码)
92
+ cookies = await self._login_with_scan()
93
+ self.session = SessionData(cookies)
94
+ self.save_session()
95
+ return cookies
96
+
97
+ async def _login_with_scan(self) -> dict:
98
+ """使用钉钉扫码登录"""
99
+ login_url = f"{self.config.kibana_base_url}/login"
100
+
101
+ async with async_playwright() as p:
102
+ browser = await p.chromium.launch(
103
+ headless=self.config.playwright_headless
104
+ )
105
+ page = await browser.new_page()
106
+
107
+ # 打开登录页
108
+ await page.goto(login_url)
109
+ print(f"请在浏览器中扫码登录: {login_url}")
110
+ print("等待扫码...")
111
+
112
+ # 等待登录成功(检测页面跳转或特定元素)
113
+ timeout = self.config.scan_timeout_seconds * 1000
114
+
115
+ try:
116
+ # 等待登录成功后的页面变化
117
+ await page.wait_for_url("**/app/kibana**", timeout=timeout)
118
+ print("登录成功!")
119
+
120
+ # 提取 cookies
121
+ cookies = {}
122
+ for cookie in await page.context.cookies():
123
+ cookies[cookie["name"]] = cookie["value"]
124
+
125
+ await browser.close()
126
+ return cookies
127
+
128
+ except Exception as e:
129
+ await browser.close()
130
+ raise Exception(f"扫码登录超时或失败: {e}")
131
+
132
+ async def resolve_short_url(self, short_url: str) -> str:
133
+ """使用浏览器解析短 URL 重定向"""
134
+ async with async_playwright() as p:
135
+ browser = await p.chromium.launch(
136
+ headless=self.config.playwright_headless
137
+ )
138
+ context = await browser.new_context()
139
+
140
+ # 设置 cookies
141
+ if self.session:
142
+ cookies_list = []
143
+ for name, value in self.session.cookies.items():
144
+ cookies_list.append({
145
+ "name": name,
146
+ "value": value,
147
+ "domain": self.config.kibana_base_url.split("//")[1].split("/")[0],
148
+ "path": "/"
149
+ })
150
+ await context.add_cookies(cookies_list)
151
+
152
+ page = await context.new_page()
153
+
154
+ # 用于捕获 _msearch 请求
155
+ captured_request = None
156
+
157
+ async def capture_request(request):
158
+ if "_msearch" in request.url:
159
+ try:
160
+ body = request.post_data
161
+ if body:
162
+ captured_request = body
163
+ except:
164
+ pass
165
+
166
+ page.on("request", capture_request)
167
+
168
+ try:
169
+ # 访问短 URL,设置超时
170
+ await page.goto(short_url, timeout=30000, wait_until="domcontentloaded")
171
+
172
+ # 等待 URL 变化(短 URL 重定向)
173
+ await page.wait_for_url("**/app/kibana**", timeout=15000)
174
+
175
+ # 等待 _msearch 请求完成
176
+ await page.wait_for_timeout(2000)
177
+
178
+ # 获取最终 URL
179
+ final_url = page.url
180
+
181
+ await browser.close()
182
+ return final_url, captured_request
183
+
184
+ except Exception as e:
185
+ await browser.close()
186
+ # 如果解析失败,返回原始 URL
187
+ return short_url, None
188
+
189
+ def get_http_client(self) -> httpx.AsyncClient:
190
+ """获取带认证的 HTTP 客户端"""
191
+ cookies = self.session.cookies if self.session else {}
192
+ return httpx.AsyncClient(
193
+ base_url=self.config.kibana_base_url,
194
+ cookies=cookies,
195
+ timeout=30.0,
196
+ )