Gitea MCP OAuth 브리지 (DCR, Gitea 로그인)
Gitea에 동적 클라이언트 등록이 없어 MCP 클라이언트가 URL만으로 OAuth 연결을 못 하는 문제를 이 브리지가 인가 서버 역할을 대신해 해결한다. G3X의 plane-mcp-oauth-bridge(upstream_oauth 모드)에서 가져와 Gitea 전용으로 정리했다: Plane PAT 연결 페이지·워크스페이스 헤더·bridge_mode 분기를 없앴다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
916d149ab5
18 files changed
+1494
No files matched your search
@@ -0,0 +1,66 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import lru_cache
|
||||
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
def parse_allowed_mcp_clients(raw: str) -> dict[str, set[str]]:
|
||||
out: dict[str, set[str]] = {}
|
||||
for part in raw.split(","):
|
||||
part = part.strip()
|
||||
if not part:
|
||||
continue
|
||||
client_id, _, redirect_uri = part.partition("|")
|
||||
client_id = client_id.strip()
|
||||
redirect_uri = redirect_uri.strip()
|
||||
if not client_id or not redirect_uri:
|
||||
continue
|
||||
out.setdefault(client_id, set()).add(redirect_uri)
|
||||
return out
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
|
||||
|
||||
public_base_url: str = "http://127.0.0.1:48080"
|
||||
listen_host: str = "0.0.0.0"
|
||||
listen_port: int = 48080
|
||||
upstream_mcp_url: str = "http://gitea-mcp:8080/mcp"
|
||||
oidc_issuer: str = ""
|
||||
oidc_client_id: str = ""
|
||||
oidc_client_secret: str = ""
|
||||
oidc_scopes: str = (
|
||||
"openid profile email write:repository write:issue write:user"
|
||||
" write:organization write:notification write:package write:misc"
|
||||
)
|
||||
allowed_mcp_clients: str = ""
|
||||
token_encryption_key: str = ""
|
||||
data_dir: str = "./data"
|
||||
dcr_enabled: bool = True
|
||||
dcr_max_clients: int = 2000
|
||||
# Forward bearer tokens the bridge did not issue (e.g. Gitea PATs) unchanged.
|
||||
passthrough_unknown_tokens: bool = True
|
||||
# Optional Host header for the upstream request (gitea-mcp rejects other hosts).
|
||||
upstream_host_header: str = ""
|
||||
|
||||
@property
|
||||
def issuer(self) -> str:
|
||||
return self.public_base_url.rstrip("/")
|
||||
|
||||
@property
|
||||
def mcp_resource_url(self) -> str:
|
||||
return f"{self.issuer}/mcp"
|
||||
|
||||
@property
|
||||
def allowed_clients(self) -> dict[str, set[str]]:
|
||||
return parse_allowed_mcp_clients(self.allowed_mcp_clients)
|
||||
|
||||
@property
|
||||
def session_secret(self) -> bytes:
|
||||
return self.token_encryption_key.encode("utf-8")
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_settings() -> Settings:
|
||||
return Settings()
|
||||
Reference in new issue
Block a user