Abdelkarim Bengrine commited on
Commit
c2ea4ad
·
1 Parent(s): 524e1e0

fix: oauth

Browse files
Files changed (3) hide show
  1. echo_server.py +8 -12
  2. math_server.py +10 -10
  3. server.py +18 -19
echo_server.py CHANGED
@@ -1,26 +1,22 @@
1
  from fastmcp import FastMCP
2
  from fastmcp.server.auth import RemoteAuthProvider
3
- from fastmcp.server.auth.providers.oauth2 import OAuth2Provider
4
  from pydantic import AnyHttpUrl
5
  import os
6
 
7
- # OAuth 2.0 configuration for Twitter/X
8
- oauth2_provider = OAuth2Provider(
9
- client_id=os.getenv("TWITTER_CLIENT_ID", "your_twitter_client_id"),
10
- client_secret=os.getenv("TWITTER_CLIENT_SECRET", "your_twitter_client_secret"),
11
- authorization_url="https://twitter.com/i/oauth2/authorize",
12
- token_url="https://api.twitter.com/2/oauth2/token",
13
  jwks_uri="https://api.twitter.com/2/oauth2/jwks",
14
- scopes=["tweet.read", "users.read"], # Add more scopes as needed
 
15
  )
16
 
17
  # Create the remote auth provider
18
  auth = RemoteAuthProvider(
19
- token_verifier=oauth2_provider,
20
  authorization_servers=[AnyHttpUrl("https://twitter.com")],
21
- base_url=os.getenv("BASE_URL", "http://localhost:8000"), # Your server base URL
22
- # Twitter OAuth 2.0 redirect URIs
23
- allowed_client_redirect_uris=["*"], # Allow all URIs for testing
24
  )
25
 
26
  mcp = FastMCP(name="EchoServer", stateless_http=True, auth=auth)
 
1
  from fastmcp import FastMCP
2
  from fastmcp.server.auth import RemoteAuthProvider
3
+ from fastmcp.server.auth.providers.jwt import JWTVerifier
4
  from pydantic import AnyHttpUrl
5
  import os
6
 
7
+ # For OAuth 2.0 with Twitter, we'll use JWT verification
8
+ # Twitter provides JWKS for token verification
9
+ token_verifier = JWTVerifier(
 
 
 
10
  jwks_uri="https://api.twitter.com/2/oauth2/jwks",
11
+ issuer="https://api.twitter.com",
12
+ audience=os.getenv("TWITTER_CLIENT_ID", "your_twitter_client_id"),
13
  )
14
 
15
  # Create the remote auth provider
16
  auth = RemoteAuthProvider(
17
+ token_verifier=token_verifier,
18
  authorization_servers=[AnyHttpUrl("https://twitter.com")],
19
+ base_url=os.getenv("BASE_URL", "https://myuniverse01-deploy1.hf.space/echo"),
 
 
20
  )
21
 
22
  mcp = FastMCP(name="EchoServer", stateless_http=True, auth=auth)
math_server.py CHANGED
@@ -1,28 +1,28 @@
1
- from mcp.server.fastmcp import FastMCP
2
- from typing import List
3
- import math
4
- import statistics
5
 
6
- mcp = FastMCP(name="MathServer", stateless_http=True)
7
 
8
 
9
- @mcp.tool(description="A simple add tool")
10
  def add_two(a: int, b: int) -> int:
11
  return a + b
12
 
13
 
14
- @mcp.tool(description="Subtract two numbers: a - b")
15
  def subtract_two(a: int, b: int) -> int:
16
  return a - b
17
 
18
 
19
- @mcp.tool(description="Multiply two numbers")
20
  def multiply(a: int, b: int) -> int:
21
  return a * b
22
 
23
 
24
- @mcp.tool(description="Divide two numbers: a / b. Raises ValueError on division by zero.")
 
 
 
25
  def divide(a: float, b: float) -> float:
26
  if b == 0:
27
- raise ValueError("Division by zero is not allowed")
28
  return a / b
 
1
+ from fastmcp import FastMCP
 
 
 
2
 
3
+ mcp = FastMCP(name='MathServer', stateless_http=True)
4
 
5
 
6
+ @mcp.tool(description='A simple add tool')
7
  def add_two(a: int, b: int) -> int:
8
  return a + b
9
 
10
 
11
+ @mcp.tool(description='Subtract two numbers: a - b')
12
  def subtract_two(a: int, b: int) -> int:
13
  return a - b
14
 
15
 
16
+ @mcp.tool(description='Multiply two numbers')
17
  def multiply(a: int, b: int) -> int:
18
  return a * b
19
 
20
 
21
+ @mcp.tool(
22
+ description='Divide two numbers: a / b. '
23
+ 'Raises ValueError on division by zero.'
24
+ )
25
  def divide(a: float, b: float) -> float:
26
  if b == 0:
27
+ raise ValueError('Division by zero is not allowed')
28
  return a / b
server.py CHANGED
@@ -1,6 +1,6 @@
1
  import contextlib
2
  from fastapi import FastAPI, Request
3
- from fastapi.responses import HTMLResponse, FileResponse
4
  from fastapi.staticfiles import StaticFiles
5
  from fastapi.templating import Jinja2Templates
6
  from echo_server import mcp as echo_mcp
@@ -8,42 +8,41 @@ from math_server import mcp as math_mcp
8
  import os
9
 
10
 
11
- # Create a combined lifespan to manage both session managers
12
  @contextlib.asynccontextmanager
13
  async def lifespan(app: FastAPI):
14
- async with contextlib.AsyncExitStack() as stack:
15
- await stack.enter_async_context(echo_mcp.session_manager.run())
16
- await stack.enter_async_context(math_mcp.session_manager.run())
17
- yield
18
 
19
 
20
  BASE_DIR = os.path.dirname(__file__)
21
- STATIC_DIR = os.path.join(BASE_DIR, "static")
22
- TEMPLATES_DIR = os.path.join(BASE_DIR, "templates")
23
 
24
  app = FastAPI(lifespan=lifespan)
25
 
26
  # Serve static assets (screenshot, styles)
27
- app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
28
 
29
  templates = Jinja2Templates(directory=TEMPLATES_DIR)
30
 
31
 
32
- @app.get("/", response_class=HTMLResponse)
33
  async def index(request: Request):
34
- space_host = os.environ.get("SPACE_HOST")
35
  if space_host and space_host.strip():
36
- base_url = space_host.strip().rstrip("/")
37
  else:
38
- base_url = f"{request.url.scheme}://{request.url.netloc}"
39
- return templates.TemplateResponse("index.html", {"request": request, "base_url": base_url})
 
 
40
 
41
 
42
- app.mount("/echo", echo_mcp.streamable_http_app())
43
- app.mount("/math", math_mcp.streamable_http_app())
44
 
45
- PORT = int(os.environ.get("PORT", "10000"))
46
 
47
- if __name__ == "__main__":
48
  import uvicorn
49
- uvicorn.run(app, host="0.0.0.0", port=PORT)
 
1
  import contextlib
2
  from fastapi import FastAPI, Request
3
+ from fastapi.responses import HTMLResponse
4
  from fastapi.staticfiles import StaticFiles
5
  from fastapi.templating import Jinja2Templates
6
  from echo_server import mcp as echo_mcp
 
8
  import os
9
 
10
 
11
+ # Create a simple lifespan (no session management needed for stateless HTTP)
12
  @contextlib.asynccontextmanager
13
  async def lifespan(app: FastAPI):
14
+ yield
 
 
 
15
 
16
 
17
  BASE_DIR = os.path.dirname(__file__)
18
+ STATIC_DIR = os.path.join(BASE_DIR, 'static')
19
+ TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')
20
 
21
  app = FastAPI(lifespan=lifespan)
22
 
23
  # Serve static assets (screenshot, styles)
24
+ app.mount('/static', StaticFiles(directory=STATIC_DIR), name='static')
25
 
26
  templates = Jinja2Templates(directory=TEMPLATES_DIR)
27
 
28
 
29
+ @app.get('/', response_class=HTMLResponse)
30
  async def index(request: Request):
31
+ space_host = os.environ.get('SPACE_HOST')
32
  if space_host and space_host.strip():
33
+ base_url = space_host.strip().rstrip('/')
34
  else:
35
+ base_url = f'{request.url.scheme}://{request.url.netloc}'
36
+ return templates.TemplateResponse(
37
+ 'index.html', {'request': request, 'base_url': base_url}
38
+ )
39
 
40
 
41
+ app.mount('/echo', echo_mcp.streamable_http_app())
42
+ app.mount('/math', math_mcp.streamable_http_app())
43
 
44
+ PORT = int(os.environ.get('PORT', '10000'))
45
 
46
+ if __name__ == '__main__':
47
  import uvicorn
48
+ uvicorn.run(app, host='0.0.0.0', port=PORT)