|
2 | 2 | import asyncio |
3 | 3 | import logging |
4 | 4 | from contextlib import asynccontextmanager |
5 | | -from typing import Annotated, Dict, Any, Optional |
6 | 5 |
|
7 | 6 | from fastmcp import FastMCP |
8 | 7 | from fastmcp.server.dependencies import get_http_request |
9 | 8 | from starlette.requests import Request |
10 | 9 | from starlette.responses import JSONResponse, HTMLResponse |
11 | 10 | import fastmcp |
12 | | -from pydantic import Field |
13 | 11 |
|
14 | | -from asktable_mcp_server.tools import ( |
| 12 | +from asktable_mcp_server.at_apis import ( |
15 | 13 | get_asktable_answer, |
16 | 14 | get_asktable_sql, |
17 | 15 | ) |
18 | 16 | from asktable_mcp_server.version import __version__ |
| 17 | +from asktable_mcp_server.schemas import ( |
| 18 | + QuestionParam, |
| 19 | + RoleIdParam, |
| 20 | + RoleVariablesParam, |
| 21 | + GEN_SQL_DESCRIPTION, |
| 22 | + QUERY_DESCRIPTION, |
| 23 | + get_home_page_html, |
| 24 | +) |
19 | 25 |
|
20 | 26 | # 配置日志 |
21 | 27 | logging.basicConfig( |
@@ -74,86 +80,18 @@ async def home(request: Request): |
74 | 80 | scheme = request.url.scheme |
75 | 81 | base_url = f"{scheme}://{host}" |
76 | 82 |
|
77 | | - content = f""" |
78 | | - <!DOCTYPE html> |
79 | | - <html> |
80 | | - <head> |
81 | | - <meta charset="utf-8"> |
82 | | - <title>AskTable MCP 服务(SSE)</title> |
83 | | - <style> |
84 | | - body {{ |
85 | | - max-width: 800px; |
86 | | - margin: 0 auto; |
87 | | - padding: 20px; |
88 | | - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; |
89 | | - line-height: 1.6; |
90 | | - }} |
91 | | - pre {{ |
92 | | - background: #f5f5f5; |
93 | | - padding: 15px; |
94 | | - border-radius: 5px; |
95 | | - overflow-x: auto; |
96 | | - }} |
97 | | - code {{ |
98 | | - white-space: pre-wrap; |
99 | | - }} |
100 | | - h1, h2 {{ |
101 | | - border-bottom: 1px solid #eee; |
102 | | - padding-bottom: 10px; |
103 | | - }} |
104 | | - ul {{ |
105 | | - padding-left: 20px; |
106 | | - }} |
107 | | - </style> |
108 | | - </head> |
109 | | - <body> |
110 | | - <h1>欢迎访问 AskTable MCP 服务(SSE)!</h1> |
111 | | - <p>当前版本: v{__version__}</p> |
112 | | -
|
113 | | - <h2>配置示例</h2> |
114 | | - <p>在您的 Agent 配置文件中,添加以下配置:</p> |
115 | | - <pre><code>{{ |
116 | | - "mcpServers": {{ |
117 | | - "asktable": {{ |
118 | | - "type": "sse", |
119 | | - "url": "{base_url}{path_prefix}/sse/?apikey=YOUR_API_KEY&datasource_id=YOUR_DATASOURCE_ID", |
120 | | - "headers": {{}}, |
121 | | - "timeout": 300, |
122 | | - "sse_read_timeout": 300 |
123 | | - }} |
124 | | - }} |
125 | | -}}</code></pre> |
126 | | -
|
127 | | - <h2>工具</h2> |
128 | | - <ul> |
129 | | - <li>使用 AskTable 生成 SQL</li> |
130 | | - <li>使用 AskTable 查询数据</li> |
131 | | - <li>列出 AskTable 中的所有数据</li> |
132 | | - </ul> |
133 | | - <h2>帮助文档</h2> |
134 | | - <p>更多详细信息,请访问 <a href="https://docs.asktable.com/docs/integration/mcp/use-asktable-mcp">使用 MCP 访问 AskTable</a></p> |
135 | | - </body> |
136 | | - </html> |
137 | | - """ |
| 83 | + content = get_home_page_html(__version__, base_url, path_prefix) |
138 | 84 | return HTMLResponse(content=content) |
139 | 85 |
|
140 | 86 | @mcp.tool(name="使用 AskTable 生成 SQL") |
141 | 87 | async def gen_sql( |
142 | | - question: Annotated[str, Field(description="用户的自然语言查询描述。示例:生成查询昨天订单总金额的SQL、写一个SQL查询销售额前10的产品、帮我写一个统计各部门员工数量的SQL")], |
143 | | - role_id: Annotated[Optional[str], Field(description="角色ID,用于访问控制,当需要进行精细化的数据访问控制时使用。示例:'role_123456',可以为空(使用默认权限)。详见:https://docs.asktable.com/docs/role-and-permission-management/introduction")] = None, |
144 | | - role_variables: Annotated[Optional[Dict[str, Any]], Field(description="角色变量,用于角色访问控制时的变量传递。示例:{'employee_id': 2}(限定员工可见范围)或{'department_id': 'dept_001'}(限定部门可见范围),可以为空(不使用变量限制)")] = None |
| 88 | + question: QuestionParam, |
| 89 | + role_id: RoleIdParam = None, |
| 90 | + role_variables: RoleVariablesParam = None |
145 | 91 | ) -> dict: |
146 | 92 | """ |
147 | | - 将自然语言查询转换为标准SQL语句。 |
148 | | - 这是一个智能SQL生成工具,可以理解用户的自然语言描述,并生成相应的SQL查询语句。 |
149 | | - 该工具仅返回SQL文本,不会执行查询操作。 |
150 | | -
|
151 | | - 适用场景: |
152 | | - - 需要将业务需求快速转换为SQL查询语句 |
153 | | - - 在执行查询前想要检查和验证SQL语句 |
154 | | - - 需要获取SQL语句用于其他系统或工具 |
155 | | - - 学习或理解如何编写特定查询的SQL语句 |
156 | | - """ |
| 93 | + {description} |
| 94 | + """.format(description=GEN_SQL_DESCRIPTION) |
157 | 95 | global server_ready |
158 | 96 |
|
159 | 97 | if not server_ready: |
@@ -182,21 +120,13 @@ async def gen_sql( |
182 | 120 |
|
183 | 121 | @mcp.tool(name="使用 AskTable 查询数据") |
184 | 122 | async def query( |
185 | | - question: Annotated[str, Field(description="用户的自然语言查询描述。示例:查询昨天订单总金额、查询销售额前10的产品、统计各部门员工数量")], |
186 | | - role_id: Annotated[Optional[str], Field(description="角色ID,用于访问控制,当需要进行精细化的数据访问控制时使用。示例:'role_123456',可以为空(使用默认权限)。详见:https://docs.asktable.com/docs/role-and-permission-management/introduction")] = None, |
187 | | - role_variables: Annotated[Optional[Dict[str, Any]], Field(description="角色变量,用于角色访问控制时的变量传递。示例:{'employee_id': 2}(限定员工可见范围)或{'department_id': 'dept_001'}(限定部门可见范围),可以为空(不使用变量限制)")] = None |
| 123 | + question: QuestionParam, |
| 124 | + role_id: RoleIdParam = None, |
| 125 | + role_variables: RoleVariablesParam = None |
188 | 126 | ) -> dict: |
189 | 127 | """ |
190 | | - 将自然语言查询转换为实际数据结果。 |
191 | | - 这是一个智能数据查询工具,可以理解用户的自然语言描述,并返回相应的查询结果。 |
192 | | -
|
193 | | - 适用场景: |
194 | | - - 需要快速获取业务数据的查询结果 |
195 | | - - 直接获取数据分析结果和洞察 |
196 | | - - 需要以自然语言方式查询数据库 |
197 | | - - 获取实时数据报表和统计信息 |
198 | | - - 通过角色访问控制实现数据安全访问 |
199 | | - """ |
| 128 | + {description} |
| 129 | + """.format(description=QUERY_DESCRIPTION) |
200 | 130 | global server_ready |
201 | 131 |
|
202 | 132 | if not server_ready: |
|
0 commit comments