pgurazada1 commited on
Commit
a26282b
·
verified ·
1 Parent(s): 00424c5

Update server.py

Browse files
Files changed (1) hide show
  1. server.py +192 -44
server.py CHANGED
@@ -1,10 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import uvicorn
3
  import inspect
4
 
5
  from mcp.server.fastmcp import FastMCP
6
  from starlette.requests import Request
7
- from starlette.responses import PlainTextResponse, JSONResponse
 
 
 
 
8
 
9
  from langchain_community.utilities import SQLDatabase
10
  from langchain_community.tools.sql_database.tool import QuerySQLCheckerTool
@@ -17,15 +127,38 @@ llm = ChatOpenAI(
17
  temperature=0
18
  )
19
 
20
- # Create an MCP server and the tool registry
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  mcp = FastMCP("Credit Card Database Server")
22
  tool_registry = []
23
 
24
  def register_tool(fn):
25
- """Decorator to register tool metadata and with MCP."""
26
- # Register with MCP
27
  mcp.tool()(fn)
28
- # Save metadata
29
  sig = inspect.signature(fn)
30
  params = [
31
  {
@@ -42,61 +175,76 @@ def register_tool(fn):
42
  })
43
  return fn
44
 
45
- credit_card_db = SQLDatabase.from_uri(r"sqlite:///data/ccms.db")
46
- query_checker_tool = QuerySQLCheckerTool(db=credit_card_db, llm=llm)
47
-
48
- @mcp.custom_route("/", methods=["GET"])
49
- async def home(request: Request) -> PlainTextResponse:
50
- return PlainTextResponse(
51
- """
52
- Credit Card Database MCP Server
53
- ----
54
- Use the following URL to connect with this server
55
- https://pgurazada1-credit-card-database-mcp-server.hf.space/mcp/
56
-
57
- Access the following URL for a list of tools and their documentation.
58
- https://pgurazada1-credit-card-database-mcp-server.hf.space/tools/
59
- """
60
- )
61
-
62
  @register_tool
63
  def sql_db_list_tables():
64
- """
65
- Returns a comma-separated list of table names in the database.
66
- """
67
  return credit_card_db.get_usable_table_names()
68
 
69
  @register_tool
70
  def sql_db_schema(table_names: list[str]) -> str:
71
- """
72
- Input 'table_names_str' is a comma-separated string of table names.
73
- Returns the DDL SQL schema for these tables.
74
- """
75
  return credit_card_db.get_table_info(table_names)
76
 
77
  @register_tool
78
  def sql_db_query_checker(query: str) -> str:
79
- """
80
- Input 'query' is a SQL query string.
81
- Checks if the query is valid.
82
- If the query is valid, it returns the original query.
83
- If the query is not valid, it returns the corrected query.
84
- This tool is used to ensure the query is valid before executing it.
85
- """
86
  return query_checker_tool.run(query)
87
 
88
  @register_tool
89
  def sql_db_query(query: str) -> str:
90
- """
91
- Input 'query' is a SQL query string.
92
- Executes the query (SELECT only) and returns the result.
93
- """
94
  return credit_card_db.run(query)
95
 
96
- @mcp.custom_route("/tools", methods=["GET"])
97
- async def list_tools(request: Request) -> JSONResponse:
98
- """Return all registered tool metadata as JSON."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  return JSONResponse(tool_registry)
100
 
101
  if __name__ == "__main__":
102
- uvicorn.run(mcp.streamable_http_app, host="0.0.0.0", port=8000)
 
1
+ # import os
2
+ # import uvicorn
3
+ # import inspect
4
+
5
+ # from mcp.server.fastmcp import FastMCP
6
+ # from starlette.requests import Request
7
+ # from starlette.responses import PlainTextResponse, JSONResponse
8
+
9
+ # from langchain_community.utilities import SQLDatabase
10
+ # from langchain_community.tools.sql_database.tool import QuerySQLCheckerTool
11
+ # from langchain_openai import ChatOpenAI
12
+
13
+ # llm = ChatOpenAI(
14
+ # api_key=os.environ.get('OPENAI_API_KEY', None),
15
+ # base_url=os.environ['OPENAI_BASE_URL'],
16
+ # model='gpt-4o-mini',
17
+ # temperature=0
18
+ # )
19
+
20
+ # # Create an MCP server and the tool registry
21
+ # mcp = FastMCP("Credit Card Database Server")
22
+ # tool_registry = []
23
+
24
+ # def register_tool(fn):
25
+ # """Decorator to register tool metadata and with MCP."""
26
+ # # Register with MCP
27
+ # mcp.tool()(fn)
28
+ # # Save metadata
29
+ # sig = inspect.signature(fn)
30
+ # params = [
31
+ # {
32
+ # "name": param.name,
33
+ # "type": str(param.annotation) if param.annotation is not inspect._empty else "Any",
34
+ # "default": param.default if param.default is not inspect._empty else None,
35
+ # }
36
+ # for param in sig.parameters.values()
37
+ # ]
38
+ # tool_registry.append({
39
+ # "name": fn.__name__,
40
+ # "description": fn.__doc__.strip() if fn.__doc__ else "",
41
+ # "parameters": params,
42
+ # })
43
+ # return fn
44
+
45
+ # credit_card_db = SQLDatabase.from_uri(r"sqlite:///data/ccms.db")
46
+ # query_checker_tool = QuerySQLCheckerTool(db=credit_card_db, llm=llm)
47
+
48
+ # @mcp.custom_route("/", methods=["GET"])
49
+ # async def home(request: Request) -> PlainTextResponse:
50
+ # return PlainTextResponse(
51
+ # """
52
+ # Credit Card Database MCP Server
53
+ # ----
54
+ # Use the following URL to connect with this server
55
+ # https://pgurazada1-credit-card-database-mcp-server.hf.space/mcp/
56
+
57
+ # Access the following URL for a list of tools and their documentation.
58
+ # https://pgurazada1-credit-card-database-mcp-server.hf.space/tools/
59
+ # """
60
+ # )
61
+
62
+ # @register_tool
63
+ # def sql_db_list_tables():
64
+ # """
65
+ # Returns a comma-separated list of table names in the database.
66
+ # """
67
+ # return credit_card_db.get_usable_table_names()
68
+
69
+ # @register_tool
70
+ # def sql_db_schema(table_names: list[str]) -> str:
71
+ # """
72
+ # Input 'table_names_str' is a comma-separated string of table names.
73
+ # Returns the DDL SQL schema for these tables.
74
+ # """
75
+ # return credit_card_db.get_table_info(table_names)
76
+
77
+ # @register_tool
78
+ # def sql_db_query_checker(query: str) -> str:
79
+ # """
80
+ # Input 'query' is a SQL query string.
81
+ # Checks if the query is valid.
82
+ # If the query is valid, it returns the original query.
83
+ # If the query is not valid, it returns the corrected query.
84
+ # This tool is used to ensure the query is valid before executing it.
85
+ # """
86
+ # return query_checker_tool.run(query)
87
+
88
+ # @register_tool
89
+ # def sql_db_query(query: str) -> str:
90
+ # """
91
+ # Input 'query' is a SQL query string.
92
+ # Executes the query (SELECT only) and returns the result.
93
+ # """
94
+ # return credit_card_db.run(query)
95
+
96
+ # @mcp.custom_route("/tools", methods=["GET"])
97
+ # async def list_tools(request: Request) -> JSONResponse:
98
+ # """Return all registered tool metadata as JSON."""
99
+ # return JSONResponse(tool_registry)
100
+
101
+ # if __name__ == "__main__":
102
+ # uvicorn.run(mcp.streamable_http_app, host="0.0.0.0", port=8000)
103
+
104
+
105
+ ##--- version with Google OAuth---
106
+
107
  import os
108
  import uvicorn
109
  import inspect
110
 
111
  from mcp.server.fastmcp import FastMCP
112
  from starlette.requests import Request
113
+ from starlette.responses import PlainTextResponse, JSONResponse, RedirectResponse
114
+ from starlette.middleware.sessions import SessionMiddleware
115
+ from fastapi import FastAPI
116
+
117
+ from authlib.integrations.starlette_client import OAuth, OAuthError
118
 
119
  from langchain_community.utilities import SQLDatabase
120
  from langchain_community.tools.sql_database.tool import QuerySQLCheckerTool
 
127
  temperature=0
128
  )
129
 
130
+ credit_card_db = SQLDatabase.from_uri(r"sqlite:///data/ccms.db")
131
+ query_checker_tool = QuerySQLCheckerTool(db=credit_card_db, llm=llm)
132
+
133
+ # Google OAuth config - set these in your environment
134
+ GOOGLE_CLIENT_ID = os.environ["GOOGLE_CLIENT_ID"]
135
+ GOOGLE_CLIENT_SECRET = os.environ["GOOGLE_CLIENT_SECRET"]
136
+ SECRET_KEY = os.environ.get("SESSION_SECRET", "supersecret") # should be set securely
137
+
138
+ # FastAPI app & session middleware
139
+ app = FastAPI()
140
+ app.add_middleware(SessionMiddleware, secret_key=SECRET_KEY)
141
+
142
+ # Set up OAuth
143
+ oauth = OAuth()
144
+ oauth.init_app(app)
145
+ CONF_URL = 'https://accounts.google.com/.well-known/openid-configuration'
146
+ oauth.register(
147
+ name='google',
148
+ client_id=GOOGLE_CLIENT_ID,
149
+ client_secret=GOOGLE_CLIENT_SECRET,
150
+ server_metadata_url=CONF_URL,
151
+ client_kwargs={
152
+ 'scope': 'openid email profile'
153
+ }
154
+ )
155
+
156
+ # MCP
157
  mcp = FastMCP("Credit Card Database Server")
158
  tool_registry = []
159
 
160
  def register_tool(fn):
 
 
161
  mcp.tool()(fn)
 
162
  sig = inspect.signature(fn)
163
  params = [
164
  {
 
175
  })
176
  return fn
177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  @register_tool
179
  def sql_db_list_tables():
180
+ """Returns a comma-separated list of table names in the database."""
 
 
181
  return credit_card_db.get_usable_table_names()
182
 
183
  @register_tool
184
  def sql_db_schema(table_names: list[str]) -> str:
185
+ """Input 'table_names_str' is a comma-separated string of table names. Returns the DDL SQL schema for these tables."""
 
 
 
186
  return credit_card_db.get_table_info(table_names)
187
 
188
  @register_tool
189
  def sql_db_query_checker(query: str) -> str:
190
+ """Checks if the query is valid. If valid, returns the original query; if not, returns the corrected query."""
 
 
 
 
 
 
191
  return query_checker_tool.run(query)
192
 
193
  @register_tool
194
  def sql_db_query(query: str) -> str:
195
+ """Executes the query (SELECT only) and returns the result."""
 
 
 
196
  return credit_card_db.run(query)
197
 
198
+ @app.route("/")
199
+ async def home(request: Request):
200
+ user = request.session.get("user")
201
+ if user:
202
+ username = user["name"]
203
+ return PlainTextResponse(f"Hello, {username}! You are logged in with Google.\nAccess /mcp/, /tools/")
204
+ else:
205
+ return PlainTextResponse("Hello! Please go to /login to sign in with Google.")
206
+
207
+ @app.route("/login")
208
+ async def login(request: Request):
209
+ redirect_uri = request.url_for('auth')
210
+ return await oauth.google.authorize_redirect(request, redirect_uri)
211
+
212
+ @app.route("/auth")
213
+ async def auth(request: Request):
214
+ try:
215
+ token = await oauth.google.authorize_access_token(request)
216
+ except OAuthError as error:
217
+ return PlainTextResponse(f"OAuth error: {error.error}")
218
+ user_info = await oauth.google.parse_id_token(request, token)
219
+ request.session["user"] = dict(user_info)
220
+ return RedirectResponse(url="/")
221
+
222
+ @app.route("/logout")
223
+ async def logout(request: Request):
224
+ request.session.pop("user", None)
225
+ return RedirectResponse(url="/")
226
+
227
+ # Protect MCP endpoints with authentication
228
+ def require_google_auth(request: Request):
229
+ user = request.session.get("user")
230
+ if not user:
231
+ return RedirectResponse(url="/login")
232
+ return user
233
+
234
+ @app.route("/mcp/{path:path}", methods=["GET", "POST"])
235
+ async def mcp_proxy(request: Request):
236
+ user = require_google_auth(request)
237
+ if isinstance(user, RedirectResponse):
238
+ return user
239
+ # forward request to MCP server (adapt as needed)
240
+ return await mcp.streamable_http_app(request.scope, request.receive, request.send)
241
+
242
+ @app.route("/tools")
243
+ async def list_tools(request: Request):
244
+ user = require_google_auth(request)
245
+ if isinstance(user, RedirectResponse):
246
+ return user
247
  return JSONResponse(tool_registry)
248
 
249
  if __name__ == "__main__":
250
+ uvicorn.run(app, host="0.0.0.0", port=8000)