Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The server runs in **two modes** from one codebase:
- **Hosted (Streamable HTTP)** — for cloud agents that connect to a URL:
**Manus** custom MCP, claude.ai connectors, ChatGPT. Multi-tenant — each
caller sends their own PAT as `Authorization: Bearer <gen_PAT>`, served at
`https://mcp.gen.pro/mcp`.
`https://mcp.gen.pro` (bare root; `/mcp` still works as a legacy alias).

## Install (local / stdio)

Expand Down Expand Up @@ -55,13 +55,13 @@ No install — point the agent at the hosted endpoint and authenticate with
your GEN PAT as a bearer token.

**Manus:** Settings → Integrations → Custom MCP Servers → Add Server
- **Server URL:** `https://mcp.gen.pro/mcp`
- **Server URL:** `https://mcp.gen.pro`
- **Authentication:** Bearer token → your `gen_…` PAT

**Self-host the HTTP transport:**

```bash
GEN_MCP_PORT=8080 gen-mcp-server --http # serves streamable-http on :8080/mcp
GEN_MCP_PORT=8080 gen-mcp-server --http # serves streamable-http on :8080 at `/` and `/mcp`
```

## The 5-Step Journey
Expand Down
21 changes: 19 additions & 2 deletions src/gen_mcp_server/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

gen-mcp-server -> stdio (default; what the PyPI/npm package ships
and what Claude Code / Cursor / VS Code run)
gen-mcp-server --http -> streamable-http on 0.0.0.0:8080/mcp
gen-mcp-server --http -> streamable-http on 0.0.0.0:8080, served at
BOTH `/` (canonical: https://mcp.gen.pro) and
`/mcp` (legacy alias for existing configs)
(hosted mode for Manus / claude.ai connectors /
ChatGPT — fronted by Cloudflare at mcp.gen.pro)

Expand Down Expand Up @@ -35,7 +37,22 @@ def main() -> None:
args = parser.parse_args()

if args.http:
mcp.run(transport="streamable-http", host=args.host, port=args.port)
import uvicorn

# Canonical MCP endpoint is the BARE root (`{"url": "https://mcp.gen.pro"}`).
# `/mcp` (the old FastMCP-default path) stays as an alias so every client
# configured before the switch keeps working — alias, not redirect, because
# MCP clients are not guaranteed to re-POST a JSON-RPC body across a 30x.
app = mcp.http_app(path="/")

async def dual_path_app(scope, receive, send): # ASGI wrapper
if scope["type"] == "http" and scope.get("path") in ("/mcp", "/mcp/"):
scope = dict(scope)
scope["path"] = "/"
scope["raw_path"] = b"/"
await app(scope, receive, send)

uvicorn.run(dual_path_app, host=args.host, port=args.port)
else:
# stdio: PAT must be present in env (fail fast, like the TS server).
if not os.environ.get("GEN_API_KEY"):
Expand Down