airsltd commited on
Commit
a823b8a
·
1 Parent(s): 742a1ff
Files changed (5) hide show
  1. .gitignore +2 -1
  2. airs/base.py +112 -0
  3. app.py +7 -0
  4. apps/airs_tasks.py +40 -0
  5. requirements.txt +2 -0
.gitignore CHANGED
@@ -1 +1,2 @@
1
- **/__pycache__/
 
 
1
+ **/__pycache__/
2
+ .env
airs/base.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from supabase import create_client, Client
3
+
4
+ # 创建 Base 类,Base类主要实现应用的用户管理,数据库连接等功能
5
+ class Base:
6
+ def __init__(self):
7
+ supabase_url = os.getenv("SUPABASE_URL")
8
+ supabase_key = os.getenv("SUPABASE_KEY")
9
+
10
+ if not supabase_url or not supabase_key:
11
+ raise ValueError("SUPABASE_URL and SUPABASE_KEY environment variables must be set.")
12
+
13
+ self.supabase: Client = create_client(supabase_url, supabase_key)
14
+
15
+ def sign_up_with_email(self, email, password):
16
+ """
17
+ 使用邮箱和密码注册新用户
18
+
19
+ Args:
20
+ email: 用户邮箱
21
+ password: 用户密码
22
+
23
+ Returns:
24
+ 成功返回用户数据,失败返回错误信息
25
+ """
26
+ try:
27
+ # 发送注册请求
28
+ response = self.supabase.auth.sign_up({
29
+ "email": email,
30
+ "password": password
31
+ })
32
+
33
+ # 检查是否有错误
34
+ if response.user is None: # Supabase Python SDK 在错误时 user 为 None
35
+ return {"success": False, "error": response.session.user.identities[0].identity_data['error']} # 尝试获取更具体的错误信息
36
+
37
+ # 注册成功
38
+ return {
39
+ "success": True,
40
+ "user": response.user.model_dump(), # 将 UserModel 转换为字典
41
+ "message": "注册成功!请检查邮箱完成验证。"
42
+ }
43
+ except Exception as e:
44
+ return {"success": False, "error": str(e)}
45
+
46
+ def sign_in_with_email(self, email, password):
47
+ """
48
+ 使用邮箱和密码登录
49
+
50
+ Args:
51
+ email: 用户邮箱
52
+ password: 用户密码
53
+
54
+ Returns:
55
+ 成功返回用户数据和会话信息,失败返回错误信息
56
+ """
57
+ try:
58
+ # 发送登录请求
59
+ response = self.supabase.auth.sign_in_with_password({
60
+ "email": email,
61
+ "password": password
62
+ })
63
+
64
+ # 检查是否有错误
65
+ if response.user is None: # Supabase Python SDK 在错误时 user 为 None
66
+ return {"success": False, "error": response.session.user.identities[0].identity_data['error']} # 尝试获取更具体的错误信息
67
+
68
+ # 登录成功,保存会话信息
69
+ return {
70
+ "success": True,
71
+ "user": response.user.model_dump(), # 将 UserModel 转换为字典
72
+ "session": response.session.model_dump(), # 将 SessionModel 转换为字典
73
+ "message": "登录成功!"
74
+ }
75
+ except Exception as e:
76
+ return {"success": False, "error": str(e)}
77
+
78
+ def get_current_user(self):
79
+ """
80
+ 获取当前登录用户
81
+
82
+ Returns:
83
+ 用户信息或 None
84
+ """
85
+ try:
86
+ # 获取当前会话
87
+ response = self.supabase.auth.get_session()
88
+
89
+ if response.session:
90
+ return response.user.model_dump() # 将 UserModel 转换为字典
91
+ else:
92
+ return None
93
+ except Exception as e:
94
+ print(f"获取用户信息出错: {str(e)}")
95
+ return None
96
+
97
+ def sign_out(self):
98
+ """
99
+ 退出登录
100
+
101
+ Returns:
102
+ 成功返回 True,失败返回 False
103
+ """
104
+ try:
105
+ response = self.supabase.auth.sign_out()
106
+ # Supabase Python SDK 的 sign_out 不直接返回 error 属性,
107
+ # 成功时通常返回 None 或一个空对象
108
+ # 如果有异常会直接抛出
109
+ return True
110
+ except Exception as e:
111
+ print(f"退出登录出错: {str(e)}")
112
+ return False
app.py CHANGED
@@ -1,11 +1,17 @@
1
  from fastapi import FastAPI
 
 
 
 
2
 
3
  from apps.app01 import App01
4
  from apps.app02 import App02
 
5
 
6
  # 初始化应用
7
  app01_instance = App01()
8
  app02_instance = App02()
 
9
 
10
  # 创建 FastAPI 应用
11
  app = FastAPI()
@@ -14,6 +20,7 @@ app = FastAPI()
14
  # 使用 Mount 来指定路径前缀
15
  app.mount("/app01", app=app01_instance.mcp.sse_app())
16
  app.mount("/app02", app=app02_instance.mcp.sse_app())
 
17
 
18
  # 根路径,用于测试 FastAPI 是否正常工作
19
  @app.get("/")
 
1
  from fastapi import FastAPI
2
+ from dotenv import load_dotenv # 导入 load_dotenv
3
+
4
+ # 加载 .env 文件中的环境变量
5
+ load_dotenv()
6
 
7
  from apps.app01 import App01
8
  from apps.app02 import App02
9
+ from apps.airs_tasks import Tasks
10
 
11
  # 初始化应用
12
  app01_instance = App01()
13
  app02_instance = App02()
14
+ tasks_instance = Tasks()
15
 
16
  # 创建 FastAPI 应用
17
  app = FastAPI()
 
20
  # 使用 Mount 来指定路径前缀
21
  app.mount("/app01", app=app01_instance.mcp.sse_app())
22
  app.mount("/app02", app=app02_instance.mcp.sse_app())
23
+ app.mount("/tasks", app=tasks_instance.mcp.sse_app())
24
 
25
  # 根路径,用于测试 FastAPI 是否正常工作
26
  @app.get("/")
apps/airs_tasks.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ from fastapi import Request
3
+ from mcp.server.fastmcp import FastMCP
4
+ import os # 用于获取环境变量
5
+ from airs.base import Base # 导入 Base 类
6
+
7
+ # 创建 MCP 应用实例
8
+ class Tasks(Base): # Tasks 类继承自 Base 类
9
+ def __init__(self):
10
+ super().__init__() # 初始化 Base 类
11
+ self.mcp = FastMCP(name="tasks", stateless_http=True)
12
+ self.register_endpoints()
13
+
14
+ # 登录测试
15
+
16
+ test_user = os.getenv("TEST_USER")
17
+ test_passsword = os.getenv("TEST_PASSWORD")
18
+ print("尝试登录...")
19
+ login_result = self.sign_in_with_email(test_user, test_passsword)
20
+ if login_result["success"]:
21
+ # print("登录成功!用户信息:", login_result["user"])
22
+ print("登录成功!")
23
+ else:
24
+ print("登录失败!错误信息:", login_result["error"])
25
+
26
+ def register_endpoints(self):
27
+ @self.mcp.resource("tasks://info")
28
+ def info() -> str:
29
+ """Information about Tasks"""
30
+ return "This is Airs Tasks"
31
+
32
+ @self.mcp.tool()
33
+ def echo(message: str) -> str:
34
+ """Echo a message in Tasks"""
35
+ return f"Tasks Echo: {message}"
36
+
37
+ @self.mcp.tool()
38
+ def app01_add_integers(num1: int, num2: int) -> int:
39
+ """Add two integers in App01"""
40
+ return num1 + num2
requirements.txt CHANGED
@@ -2,3 +2,5 @@ fastapi
2
  uvicorn
3
  fastmcp
4
  sse_starlette
 
 
 
2
  uvicorn
3
  fastmcp
4
  sse_starlette
5
+ supabase
6
+ python-dotenv