{
  "markdown": "# srgplus-mcp\n\n<!-- MCP Registry ownership proof — required by mcp-publisher for the\n     io.github.srgplus/* namespace. Do not remove. -->\nmcp-name: io.github.srgplus/srgplus-mcp\n\nMCP server for [SRG+](https://srgplus.com) — lets Claude (and any MCP-aware\nagent) manage hubs, channels, content, assets, users, and workspaces through\nthe SRG+ API.\n\nTwo ways to run it:\n\n- **Hosted HTTP** (recommended for production / claude.ai web / Cursor / Cline) — single endpoint, header-based auth, multi-tenant\n- **Local stdio** (for desktop dev / offline) — single user, env-var auth, runs as a child process of the agent\n\nBoth modes share the same tools and the same SDK underneath — you pick the\ntransport that fits your client.\n\n## Hosted HTTP\n\n### Run the server\n\n```bash\npip install 'srgplus-mcp[server]'\nsrgplus-mcp-serve   # listens on $PORT (default 8090)\n```\n\nOr in Docker:\n\n```bash\ndocker build -t srgplus-mcp .\ndocker run -p 8090:8090 srgplus-mcp\n```\n\nHealth check:\n\n```bash\ncurl http://localhost:8090/health\n```\n\n### Connect from Claude / Cursor / any MCP client\n\n```json\n{\n  \"mcpServers\": {\n    \"srgplus\": {\n      \"url\": \"http://localhost:8090/mcp\",\n      \"headers\": { \"X-API-Key\": \"srgplus_your_key_here\" }\n    }\n  }\n}\n```\n\nOr use `Authorization: Bearer srgplus_...` instead of `X-API-Key` — both work.\n\nFor a hosted public endpoint pointed at your SRG+ workspace, the URL becomes\n`https://mcp.srgplus.com/mcp` (rolling out — see SRGDEV-8 follow-ups for the\ndeploy plan).\n\n## OAuth (claude.ai web, Connectors Gallery, ChatGPT Apps)\n\nFor browser-based clients that require OAuth 2.1 (DCR + PKCE):\n\n1. In claude.ai → **Settings → Connectors → Add custom connector**\n2. URL: `https://mcp.srgplus.com/mcp`\n3. Leave OAuth fields empty — the wizard will discover, DCR-register, and\n   redirect to a consent page\n4. On the consent page: paste your SRG+ workspace API key\n5. Tools appear in claude.ai\n\nEndpoints exposed (all under the same hostname as `/mcp`):\n\n| Endpoint | Purpose |\n|----------|---------|\n| `/.well-known/oauth-authorization-server` | RFC 8414 metadata |\n| `/.well-known/oauth-protected-resource` | RFC 9728 metadata |\n| `/oauth/register` | RFC 7591 Dynamic Client Registration |\n| `/oauth/authorize` | Authorization endpoint with consent page |\n| `/oauth/token` | Token endpoint (PKCE S256 required) |\n| `/oauth/revoke` | RFC 7009 revocation |\n\n**Backwards compatibility:** the `X-API-Key` header and `Authorization:\nBearer srgplus_...` flows from above still work. OAuth tokens (RFC-shaped\nJWTs) are detected automatically when the bearer value doesn't start with\n`srgplus_`.\n\n### Multiple workspaces\n\nEach SRG+ workspace API key is scoped to a single workspace, so one OAuth\nsession today connects one workspace.\n\nTo connect Claude to **several workspaces at once**, add the SRG+ connector\nmultiple times in claude.ai → Settings → Connectors. Each instance goes\nthrough its own OAuth flow with the API key for that workspace:\n\n```\nSRG+ (Acme)       → https://mcp.srgplus.com/mcp  → API key for Acme workspace\nSRG+ (Personal)   → https://mcp.srgplus.com/mcp  → API key for Personal workspace\nSRG+ (Studios)    → https://mcp.srgplus.com/mcp  → API key for Studios workspace\n```\n\nTools from each connector show up in claude.ai under their connector name,\nso you can scope a request to a specific workspace by mentioning the\nconnector (\"use SRG+ Acme to find content X\").\n\nA single-OAuth multi-workspace flow (Airtable-style: pick multiple\nworkspaces in one consent screen, server provisions scoped keys\nautomatically) is tracked in\n[SRGDEV-27](https://sergecreator.atlassian.net/browse/SRGDEV-27) and will\nland in a future release. Until then, the multi-connector approach above\ncovers the same use case with no extra code.\n\n### Production secrets\n\nIn production, set these via GCP Secret Manager so token state survives\nprocess restarts:\n\n| Env var | Purpose |\n|---------|---------|\n| `OAUTH_ISSUER` | Canonical issuer URL (e.g. `https://mcp.srgplus.com`) |\n| `OAUTH_CLIENT_REGISTRATION_KEY` | HMAC key for DCR `client_id` JWTs |\n| `OAUTH_TOKEN_SIGNING_KEY` | HMAC key for codes/access/refresh tokens |\n| `OAUTH_API_KEY_ENCRYPTION_KEY` | 32-byte AES-GCM key (base64url) for wrapping the SRG+ workspace api_key inside JWTs |\n\nIf any are unset the server generates an ephemeral random key per process —\nfine for local development, but every process restart invalidates all\nin-flight authorizations.\n\n### How auth works\n\nEach request must carry the workspace API key in either header:\n\n- `X-API-Key: srgplus_...`\n- `Authorization: Bearer srgplus_...`\n\nThe server doesn't pre-validate the key — it binds it to the SDK's\nper-request contextvar via `SRGClient.use_api_key(...)` and lets the SRG+\nSDK make the actual call. Bad keys surface as 401 from the upstream API on\nthe first tool invocation.\n\nA single shared `SRGClient` (and therefore a single `httpx` connection pool)\nserves every request, so the per-request overhead is just a contextvar\nset/reset — no per-key client construction or cache.\n\n## Local stdio (developer mode)\n\nUse this when you're building locally against SRG+ and want a child-process\nMCP without running an HTTP server.\n\n### Claude Desktop\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"srgplus\": {\n      \"command\": \"uvx\",\n      \"args\": [\"srgplus-mcp\"],\n      \"env\": {\n        \"SRG_API_KEY\": \"srgplus_your_key_here\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Desktop. The `uvx` command downloads and runs the package\nautomatically — no separate install step needed.\n\n### Claude Code\n\n```bash\nclaude mcp add srgplus -- uvx srgplus-mcp\nexport SRG_API_KEY=srgplus_your_key_here\n```\n\n## Getting an API key\n\nLog in to SRG+ → **Settings → Workspaces → Select Workspace → API Keys** →\ncreate a new key. Use the same key for both stdio (`SRG_API_KEY` env var) and\nhosted HTTP (`X-API-Key` header).\n\n## Available tools\n\n### Hub Profiles\n`list_hub_profiles` · `list_managed_hub_profiles` · `get_hub_profile` · `get_hub_profile_by_username` · `filter_hub_profiles` · `create_hub_profile` · `update_hub_profile` · `archive_hub_profile` · `restore_hub_profile` · `delete_hub_profile` · `join_hub_profile` · `invite_to_hub_profile` · `list_invitations` · `update_invitation` · `delete_invitation` · `get_invitation_link` · `move_hub_profile_to_workspace` · `turn_on_hub_profile_community`\n\n### Channels\n`list_channels` · `get_channel` · `get_channel_by_name` · `create_channel` · `update_channel` · `archive_channel` · `delete_channel` · `create_category` · `update_category` · `archive_category` · `delete_category` · `get_category_by_slugs` · `create_section` · `update_section` · `delete_section`\n\n### Contents\n`list_contents` · `get_content` · `get_content_v2` · `create_content` · `update_content` · `move_content` · `search_contents` · `add_content_to_category` · `add_content_to_categories` · `remove_content_from_categories` · `get_category_references` · `create_content_section` · `update_content_section` · `delete_content_section` · `add_subcontent` · `get_subcontent` · `move_subcontent` · `delete_subcontent` · `patch_content_progression` · `get_progression_stats`\n\n### Assets\n`upload_asset` · `list_assets` · `get_asset` · `search_assets` · `create_embed_asset` · `update_asset` · `patch_media_progression`\n\n> `upload_asset` creates an asset and uploads its bytes in one call (from a `source_url` or `base64_content`) — use it for any file, image, or video. The older `create_image_asset` / `create_video_asset` / `create_file_asset` / `create_media_asset` tools only register an empty record and are deprecated.\n\n### Users & Permissions\n`get_user` · `check_user_exists_by_email` · `check_user_exists_by_phone` · `get_workspace_users` · `give_permission` · `delete_permission` · `can_read` · `can_edit` · `can_archive` · `can_create_child` · `can_manage_permissions` · `is_member` · `get_permission_targets` · `list_permission_groups` · `get_permission_group` · `create_permission_group` · `update_permission_group` · `delete_permission_group` · `add_users_to_permission_group` · `remove_user_from_permission_group`\n\n### Workspace\n`get_workspace` · `update_workspace` · `get_workspace_hub_profiles` · `list_workspace_actions` · `get_workspace_action` · `create_workspace_action` · `update_workspace_action` · `delete_workspace_action` · `invite_to_workspace` · `get_workspace_invitation_link` · `list_workspace_invitations` · `update_workspace_invitation` · `delete_workspace_invitation`\n",
  "bytes": 8484,
  "sha": "f2c5eded1b1fe8c6a93ebd7f74253967516a0a6316b5137561964d842ced7fdf",
  "repo_slug": "srgplus/srgplus-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_srgplus_srgplus_mcp_c58cffa4/readme"
}