Skip to content

Add hosted API portal: server, EyerollAPIBackend, MCP server, skills#3

Open
mnvsk97 wants to merge 2 commits intomainfrom
claude/stripe-payment-api-portal-K16Zr
Open

Add hosted API portal: server, EyerollAPIBackend, MCP server, skills#3
mnvsk97 wants to merge 2 commits intomainfrom
claude/stripe-payment-api-portal-K16Zr

Conversation

@mnvsk97
Copy link
Copy Markdown
Owner

@mnvsk97 mnvsk97 commented Apr 14, 2026

  • eyeroll/server/: FastAPI app (main.py) + asyncpg DB helpers (db.py)

    • minimal dark landing page (static/index.html)
      Routes: GET / POST /signup POST|GET /api/watch|usage|keys/rotate
      PostgreSQL-backed (asyncpg, raw SQL), rate-limited at 20 analyses/day
  • eyeroll/backend.py: EyerollAPIBackend — routes watch() calls to the
    hosted API when EYEROLL_API_KEY is set; auto-selected in get_backend()

  • eyeroll/watch.py: short-circuit for EyerollAPIBackend (calls backend.watch()
    directly, skipping local extract/analyze pipeline)

  • eyeroll/cli.py: add eyeroll-api to --backend choices; auto-detect
    EYEROLL_API_KEY for default backend and parallel worker count

  • eyeroll/mcp_server.py: stdio MCP server exposing watch_video,
    check_usage, rotate_key tools; entry point: eyeroll-mcp

  • plugins/eyeroll/commands/api-{watch,usage,rotate-key}.md: Claude Code
    slash command skills wrapping the hosted API endpoints

  • pyproject.toml: add [server] optional deps (fastapi, uvicorn, asyncpg,
    python-multipart, google-genai, openai); add eyeroll-mcp script entry

https://claude.ai/code/session_01BiJUMiryNmWRbnkzQbzjmH

- eyeroll/server/: FastAPI app (main.py) + asyncpg DB helpers (db.py)
  + minimal dark landing page (static/index.html)
  Routes: GET / POST /signup POST|GET /api/watch|usage|keys/rotate
  PostgreSQL-backed (asyncpg, raw SQL), rate-limited at 20 analyses/day

- eyeroll/backend.py: EyerollAPIBackend — routes watch() calls to the
  hosted API when EYEROLL_API_KEY is set; auto-selected in get_backend()

- eyeroll/watch.py: short-circuit for EyerollAPIBackend (calls backend.watch()
  directly, skipping local extract/analyze pipeline)

- eyeroll/cli.py: add eyeroll-api to --backend choices; auto-detect
  EYEROLL_API_KEY for default backend and parallel worker count

- eyeroll/mcp_server.py: stdio MCP server exposing watch_video,
  check_usage, rotate_key tools; entry point: eyeroll-mcp

- plugins/eyeroll/commands/api-{watch,usage,rotate-key}.md: Claude Code
  slash command skills wrapping the hosted API endpoints

- pyproject.toml: add [server] optional deps (fastapi, uvicorn, asyncpg,
  python-multipart, google-genai, openai); add eyeroll-mcp script entry

https://claude.ai/code/session_01BiJUMiryNmWRbnkzQbzjmH
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f83f171135

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread eyeroll/server/db.py Outdated
Comment on lines +53 to +55
row = await conn.fetchrow("SELECT id, email, api_key FROM users WHERE email = $1", email)
if row:
return dict(row)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Stop exposing existing API keys on repeated signup

This branch returns the full existing api_key whenever /signup is called with an email that is already registered, and /signup is unauthenticated. That means anyone who can guess a user's email can retrieve that user's active credential and immediately call protected endpoints as them (including rotating their key). Treat existing-user signups as non-disclosive (or require ownership verification) instead of returning stored keys.

Useful? React with 👍 / 👎.

Comment thread eyeroll/backend.py
import urllib.request
import json as _json

payload = _json.dumps({"source": source, "context": context, "max_frames": max_frames}).encode()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Upload local media instead of sending filesystem paths

The hosted backend forwards source as a JSON string only, so a call like eyeroll watch ./recording.mp4 sends a client-local path that the API server cannot read from its own filesystem. Because this backend is auto-selected when EYEROLL_API_KEY is set and the docs advertise local-file support, local analyses will fail for those users unless the client uploads file bytes (or explicitly falls back to local processing for local paths).

Useful? React with 👍 / 👎.

Comment thread eyeroll/watch.py
if isinstance(backend, EyerollAPIBackend):
if verbose:
print(f"Backend: eyeroll-api (hosted)", file=sys.stderr)
return backend.watch(source=source, context=context, max_frames=max_frames)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reset backend cache before returning from API fast path

This early return bypasses the normal finally path that calls reset_backend(). Since get_backend() always returns a cached backend once initialized, one watch() call that uses EyerollAPIBackend can pin the process to that backend and cause later watch(..., backend_name="gemini") calls in the same process to still route to the hosted API.

Useful? React with 👍 / 👎.

DB (db.py):
- New api_keys table: users can have multiple named keys
- Auth lookup now joins api_keys → users, returns key_id for usage tracking
- log_usage() tracks key_id per analysis
- Key CRUD: create_key, list_keys, rename_key, delete_key (guards last key)

Server (main.py):
- POST /signup returns {api_key, key_id, key_name}
- GET  /api/keys — list all keys for authenticated user
- POST /api/keys — create a new key {name?}
- PATCH /api/keys/{id} — rename a key
- DELETE /api/keys/{id} — revoke a key (400 if last)
- Removed /api/keys/rotate (replaced by create + delete pattern)

MCP server (mcp_server.py):
- Added signup, keys_list, keys_create, keys_rename, keys_delete tools
- signup tool requires no auth (bootstrapping flow)
- Bumped server version to 0.2.0

Claude Code skills (plugins/eyeroll/commands/):
- signup.md        — interactive signup flow
- keys-list.md     — list keys with masked display
- keys-create.md   — create key with optional name
- keys-delete.md   — revoke with last-key guard warning
- keys-rename.md   — rename by key ID

https://claude.ai/code/session_01BiJUMiryNmWRbnkzQbzjmH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants