File size: 4,447 Bytes
19b4e98
0629dc1
 
 
 
19b4e98
 
 
 
 
 
 
 
 
 
0629dc1
 
 
19b4e98
91d2e72
19b4e98
 
 
3089135
 
 
91d2e72
0629dc1
 
19b4e98
 
 
 
 
91d2e72
0629dc1
19b4e98
 
0629dc1
 
 
91d2e72
0629dc1
19b4e98
 
 
 
 
 
 
 
 
3089135
 
 
 
 
 
 
19b4e98
3089135
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0629dc1
 
19b4e98
0629dc1
 
91d2e72
 
19b4e98
 
0629dc1
19b4e98
0629dc1
 
 
91d2e72
0629dc1
 
19b4e98
 
0629dc1
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python3
import argparse
import os
from pathlib import Path

from huggingface_hub import HfApi, whoami, create_repo, upload_folder


def repo_url(space_id: str) -> str:
    return f"https://huggingface.co/spaces/{space_id}"


def app_url(space_id: str) -> str:
    owner, name = space_id.split("/", 1)
    return f"https://{owner}-{name}.hf.space"


def main() -> None:
    parser = argparse.ArgumentParser(description="Create/sync the mcp-bridge Hugging Face Docker Space.")
    parser.add_argument("--space-id", default="patdev/mcp-bridge", help="HF Space ID, e.g. patdev/mcp-bridge")
    parser.add_argument("--api-key", default=os.getenv("MCP_API_KEY", ""), help="Value for Space secret MCP_API_KEY")
    parser.add_argument("--oauth-signing-key", default=os.getenv("MCP_OAUTH_SIGNING_KEY", ""), help="Optional Space secret MCP_OAUTH_SIGNING_KEY")
    parser.add_argument("--public-base-url", default="", help="Public base URL, defaults to https://owner-name.hf.space")
    parser.add_argument("--chatgpt-callback-url", default="", help="Optional exact ChatGPT OAuth callback URL allowlist. Not required by default; ChatGPT callback prefix is accepted.")
    parser.add_argument("--oauth-client-id", default=os.getenv("OAUTH_STATIC_CLIENT_ID", "chatgpt"), help="Manual OAuth client ID for ChatGPT when DCR is unavailable")
    parser.add_argument("--oauth-client-secret", default=os.getenv("OAUTH_STATIC_CLIENT_SECRET", ""), help="Optional manual OAuth client secret")
    parser.add_argument("--restart", action="store_true", help="Restart the Space after upload")
    args = parser.parse_args()

    if "/" not in args.space_id:
        raise SystemExit("--space-id must look like owner/name")
    if not args.api_key:
        raise SystemExit("Missing --api-key or MCP_API_KEY env var")

    root = Path(__file__).resolve().parents[1]
    api = HfApi()
    me = whoami()
    print(f"Authenticated as: {me.get('name') or me}")
    print(f"Space ID: {args.space_id}")

    print("Creating Space if needed...")
    create_repo(args.space_id, repo_type="space", space_sdk="docker", exist_ok=True)

    public_base = (args.public_base_url or app_url(args.space_id)).rstrip("/")

    print("Setting Space Secret MCP_API_KEY...")
    api.add_space_secret(repo_id=args.space_id, key="MCP_API_KEY", value=args.api_key)

    if args.oauth_signing_key:
        print("Setting Space Secret MCP_OAUTH_SIGNING_KEY...")
        api.add_space_secret(repo_id=args.space_id, key="MCP_OAUTH_SIGNING_KEY", value=args.oauth_signing_key)

    def set_space_var(key: str, value: str) -> None:
        try:
            api.add_space_variable(repo_id=args.space_id, key=key, value=value)
        except AttributeError:
            # Older huggingface_hub fallback: harmless, but secret instead of variable.
            api.add_space_secret(repo_id=args.space_id, key=key, value=value)

    print(f"Setting Space Variable PUBLIC_BASE_URL={public_base}")
    set_space_var("PUBLIC_BASE_URL", public_base)

    if args.oauth_client_id:
        print(f"Setting Space Variable OAUTH_STATIC_CLIENT_ID={args.oauth_client_id}")
        set_space_var("OAUTH_STATIC_CLIENT_ID", args.oauth_client_id)

    if args.chatgpt_callback_url:
        print("Setting Space Variable OAUTH_ALLOWED_REDIRECT_URIS=<exact ChatGPT callback URL>")
        set_space_var("OAUTH_ALLOWED_REDIRECT_URIS", args.chatgpt_callback_url.strip())
    else:
        print("Using default ChatGPT redirect prefix allow: https://chatgpt.com/connector/oauth/*")
        set_space_var("OAUTH_ALLOW_CHATGPT_REDIRECT_PREFIX", "true")

    if args.oauth_client_secret:
        print("Setting Space Secret OAUTH_STATIC_CLIENT_SECRET")
        api.add_space_secret(repo_id=args.space_id, key="OAUTH_STATIC_CLIENT_SECRET", value=args.oauth_client_secret)

    print("Uploading project files...")
    info = upload_folder(
        repo_id=args.space_id,
        repo_type="space",
        folder_path=str(root),
        path_in_repo=".",
        ignore_patterns=[".git", ".hf", "__pycache__", "*.pyc", ".env", "*.zip"],
        commit_message="Update mcp-bridge OAuth server",
    )
    print(f"Uploaded: {getattr(info, 'commit_url', info)}")

    if args.restart:
        print("Restarting Space...")
        api.restart_space(repo_id=args.space_id)

    print("\nDone.")
    print(f"Space: {repo_url(args.space_id)}")
    print(f"MCP SSE: {public_base}/sse")


if __name__ == "__main__":
    main()