{"id":49530901,"url":"https://github.com/jakub-k-slys/substack-gateway-oss","last_synced_at":"2026-05-02T07:33:45.124Z","repository":{"id":353762660,"uuid":"1185648838","full_name":"jakub-k-slys/substack-gateway-oss","owner":"jakub-k-slys","description":"Stateless Substack Gateway exposing a REST API and MCP for reading profiles, posts, notes, and comments, plus authenticated personal and note-publishing workflows.","archived":false,"fork":false,"pushed_at":"2026-04-25T11:20:33.000Z","size":2017,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-25T13:24:41.740Z","etag":null,"topics":["ai-tools","automation","fastapi","fastmcp","gateway","integration","mcp","model-context-protocol","python","rest","rest-api","substack","vercel"],"latest_commit_sha":null,"homepage":"https://substack-gateway-oss.readthedocs.io/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jakub-k-slys.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-18T20:01:34.000Z","updated_at":"2026-04-25T11:21:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jakub-k-slys/substack-gateway-oss","commit_stats":null,"previous_names":["jakub-k-slys/substack-gateway-oss"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/jakub-k-slys/substack-gateway-oss","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakub-k-slys%2Fsubstack-gateway-oss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakub-k-slys%2Fsubstack-gateway-oss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakub-k-slys%2Fsubstack-gateway-oss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakub-k-slys%2Fsubstack-gateway-oss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jakub-k-slys","download_url":"https://codeload.github.com/jakub-k-slys/substack-gateway-oss/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakub-k-slys%2Fsubstack-gateway-oss/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32527138,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T01:12:54.858Z","status":"online","status_checked_at":"2026-05-02T02:00:05.923Z","response_time":132,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-tools","automation","fastapi","fastmcp","gateway","integration","mcp","model-context-protocol","python","rest","rest-api","substack","vercel"],"created_at":"2026-05-02T07:33:44.476Z","updated_at":"2026-05-02T07:33:45.104Z","avatar_url":"https://github.com/jakub-k-slys.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Substack Gateway OSS\n\n[![CI](https://github.com/jakub-k-slys/substack-gateway-oss/actions/workflows/ci.yaml/badge.svg)](https://github.com/jakub-k-slys/substack-gateway-oss/actions/workflows/ci.yaml)\n[![E2E Tests](https://github.com/jakub-k-slys/substack-gateway-oss/actions/workflows/e2e.yaml/badge.svg)](https://github.com/jakub-k-slys/substack-gateway-oss/actions/workflows/e2e.yaml)\n[![Deployed on Vercel](https://img.shields.io/badge/deployed%20on-Vercel-000000?logo=vercel)](https://substack-gateway.vercel.app)\n\nA stateless Python gateway for [Substack](https://substack.com) that exposes a\nREST API and an MCP server on top of the same service layer.\n\nIt is designed to make Substack data and actions easier to consume from scripts,\napplications, and AI tooling without duplicating integration logic across\ndifferent interfaces.\n\n## What You Can Do\n\n- Read public Substack profiles, posts, notes, and comments\n- Access authenticated `me` endpoints with a base64-encoded credential token\n- Create and delete notes through the REST API\n- Use the same gateway as an MCP server for AI tools and agent workflows\n- Extend the app with custom routes, MCP tools, auth providers, and lifespan\n  hooks\n\n## Interfaces\n\n- **REST API** at `/api/v1/*`\n- **MCP server** at `/mcp`\n\nBoth share the same service layer and HTTP clients.\n\n## Quickstart\n\nRequirements:\n\n- Python 3.10+\n- [uv](https://docs.astral.sh/uv/)\n\nInstall dependencies:\n\n```bash\nuv sync --dev\n```\n\nRun the application locally:\n\n```bash\nuv run python -m gateway_oss.main\n```\n\nCheck the root metadata endpoint:\n\n```bash\ncurl http://127.0.0.1:5001/\n```\n\nCheck the liveness probe:\n\n```bash\ncurl http://127.0.0.1:5001/api/v1/health/live\n```\n\nFetch a public profile:\n\n```bash\ncurl http://127.0.0.1:5001/api/v1/profiles/\u003cslug\u003e\n```\n\n## REST Example\n\nPublic profile lookup:\n\n```bash\ncurl http://127.0.0.1:5001/api/v1/profiles/\u003cslug\u003e\n```\n\nAuthenticated request:\n\n```bash\ncurl \\\n  -H \"x-gateway-token: \u003cbase64-encoded-json\u003e\" \\\n  http://127.0.0.1:5001/api/v1/me\n```\n\nThe REST API is mounted under `/api/v1` and includes endpoints for health,\nprofiles, posts, notes, comments, and authenticated `me` operations.\n\n## Authentication\n\nGateway access and Substack access are separate concerns.\n\nFor this OSS repository, Substack credentials are passed as a base64-encoded\nJSON object. REST requests send that value as the `x-gateway-token` header.\n\nCredential shape:\n\n```json\n{\n  \"publication_url\": \"https://example.substack.com\",\n  \"substack_sid\": \"s%3A...\",\n  \"connect_sid\": \"s%3A...\"\n}\n```\n\nEncode it with:\n\n```bash\necho '{\"publication_url\":\"https://example.substack.com\",\"substack_sid\":\"s%3A...\",\"connect_sid\":\"s%3A...\"}' | base64\n```\n\nTreat `substack_sid` and `connect_sid` as bearer credentials. Do not commit\nreal values to the repository.\n\n## MCP\n\nThe MCP server is mounted at `/mcp` and served over streamable HTTP.\n\nPublic OSS MCP tools include:\n\n- `get_note`\n- `get_post`\n- `get_post_comments`\n- `get_profile`\n- `get_profile_posts`\n- `get_profile_notes`\n\n## Project Layout\n\nCore application code lives in `src/gateway_oss/`.\n\n- `api/v1/`: FastAPI route handlers\n- `mcp/`: FastMCP tool surface and transport integration\n- `services/`: shared business logic\n- `client/`: Substack HTTP client wrappers\n- `models/`: schemas and pagination models\n- `converters/`: Markdown conversion\n- `extensions/`: runtime extension hooks\n\n## Configuration\n\nApplication settings are environment-driven via the `SUBSTACK_GATEWAY_` prefix.\n\nCommon examples include:\n\n- `SUBSTACK_GATEWAY_LOG_LEVEL`\n- `SUBSTACK_GATEWAY_SUBSTACK_BASE_URL`\n- `SUBSTACK_GATEWAY_SUBSTACK_TIMEOUT_SEC`\n\n## Documentation\n\nThe repository includes MkDocs and Read the Docs configuration:\n\n- [Docs home](docs/index.md)\n- [Introduction](docs/introduction.md)\n- [Installation guide](docs/installation.md)\n- [Authentication](docs/authentication.md)\n- [API reference](docs/api-reference.md)\n- [MCP documentation](docs/mcp.md)\n- [Development guide](docs/development.md)\n- [Contributing guide](CONTRIBUTING.md)\n\nRead the Docs can build the site directly from `.readthedocs.yaml` and `mkdocs.yml`.\n\n## Validation\n\n```bash\nuv run ruff check .\nuv run ruff format --check .\nuv run ty check .\nuv build\nuv run pytest tests/\nuv run behave features/\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakub-k-slys%2Fsubstack-gateway-oss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjakub-k-slys%2Fsubstack-gateway-oss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakub-k-slys%2Fsubstack-gateway-oss/lists"}