Skip to content

Commit 6e408fd

Browse files
Copilotjirispilka
andauthored
fix: Move streamable HTTP transport from /mcp to root / (#529)
* Initial plan * Move streamable transport from /mcp to root / Co-authored-by: jirispilka <19406805+jirispilka@users.noreply.github.com> * Update src/actor/server.ts * Remove GET / handler and update DEVELOPMENT.md endpoint references Co-authored-by: jirispilka <19406805+jirispilka@users.noreply.github.com> * Revert MCP_STREAMABLE_ENDPOINT change in src/const.ts Co-authored-by: jirispilka <19406805+jirispilka@users.noreply.github.com> * refactor: Update MCP route to return 405 for unsupported GET requests --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jirispilka <19406805+jirispilka@users.noreply.github.com> Co-authored-by: Jiří Spilka <jiri.spilka@apify.com> Co-authored-by: Jiri Spilka <jirka.spilka@gmail.com>
1 parent 692411f commit 6e408fd

4 files changed

Lines changed: 7 additions & 40 deletions

File tree

DEVELOPMENT.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ This command builds the core project and the `src/web/` widgets, then copies the
6666

6767
All widget code lives in the self-contained `src/web/` React project. The widgets (MCP Apps) are rendered based on the structured output returned by MCP tools. If you need to add specific data to a widget, modify the corresponding MCP tool's output, since widgets can only render data returned by the MCP tool call result.
6868

69-
> **Important (UI mode):** Widget rendering is enabled only when the server runs in UI mode. Use the `ui=openai` query parameter (e.g., `/mcp?ui=openai`) or set `UI_MODE=openai`. Currently, `openai` is the only supported `ui` value.
69+
> **Important (UI mode):** Widget rendering is enabled only when the server runs in UI mode. Use the `ui=openai` query parameter (e.g., `/?ui=openai`) or set `UI_MODE=openai`. Currently, `openai` is the only supported `ui` value.
7070
7171
### Hot-reload development
7272

@@ -150,7 +150,7 @@ You can use [MCPJam](https://www.mcpjam.com/) to connect to and test the MCP ser
150150

151151
1. Click **"Add new server"**
152152
2. Fill in a name for the server
153-
3. Enter the URL: `http://localhost:3001/mcp?ui=openai` (Note: the `ui=openai` query parameter is required for widget rendering)
153+
3. Enter the URL: `http://localhost:3001/?ui=openai` (Note: the `ui=openai` query parameter is required for widget rendering)
154154
4. Select **"No authentication"** as the auth method
155155
5. Click **Add**
156156

@@ -196,13 +196,13 @@ Then start the tunnel:
196196
ngrok start app
197197
```
198198

199-
The MCP server API will be reachable at `https://mcp-apify.ngrok.dev/mcp?ui=openai`.
199+
The MCP server API will be reachable at `https://mcp-apify.ngrok.dev/?ui=openai`.
200200

201201
#### Adding the server in ChatGPT
202202

203203
1. Go to [chatgpt.com](https://chatgpt.com) and open **Settings → Connectors**
204204
2. Click **"Add a custom connector"**
205-
3. Enter the URL: `https://mcp-apify.ngrok.dev/mcp?ui=openai`
205+
3. Enter the URL: `https://mcp-apify.ngrok.dev/?ui=openai`
206206
4. Save and start a new chat
207207

208208
> **Important:** After restarting ngrok, use the **Refresh** button in the connector settings to reconnect — ChatGPT does not detect the tunnel restart automatically.

package-lock.json

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/actor/const.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ export enum TransportType {
99
}
1010

1111
export enum Routes {
12-
ROOT = '/',
13-
MCP = '/mcp',
12+
MCP = '/',
1413
SSE = '/sse',
1514
MESSAGE = '/message',
1615
}

src/actor/server.ts

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ import { ApifyClient } from '../apify_client.js';
1818
import { ActorsMcpServer } from '../mcp/server.js';
1919
import type { ApifyRequestParams } from '../types.js';
2020
import { parseUiMode } from '../types.js';
21-
import { getHelpMessage, HEADER_READINESS_PROBE, Routes, TransportType } from './const.js';
22-
import { getActorRunData } from './utils.js';
21+
import { getHelpMessage, Routes, TransportType } from './const.js';
2322

2423
export function createExpressApp(
2524
host: string,
@@ -51,31 +50,6 @@ export function createExpressApp(
5150
}
5251
}
5352

54-
app.get(Routes.ROOT, async (req: Request, res: Response) => {
55-
if (req.headers && req.get(HEADER_READINESS_PROBE) !== undefined) {
56-
log.debug('Received readiness probe');
57-
res.status(200).json({ message: 'Server is ready' }).end();
58-
return;
59-
}
60-
try {
61-
log.info('MCP API', {
62-
mth: req.method,
63-
rt: Routes.ROOT,
64-
tr: TransportType.HTTP,
65-
});
66-
res.setHeader('Content-Type', 'text/event-stream');
67-
res.setHeader('Cache-Control', 'no-cache');
68-
res.setHeader('Connection', 'keep-alive');
69-
res.status(200).json({ message: `Actor is using Model Context Protocol. ${getHelpMessage(host)}`, data: getActorRunData() }).end();
70-
} catch (error) {
71-
respondWithError(res, error, `Error in GET ${Routes.ROOT}`);
72-
}
73-
});
74-
75-
app.head(Routes.ROOT, (_req: Request, res: Response) => {
76-
res.status(200).end();
77-
});
78-
7953
app.get(Routes.SSE, async (req: Request, res: Response) => {
8054
try {
8155
log.info('MCP API', {
@@ -192,7 +166,7 @@ export function createExpressApp(
192166
});
193167

194168
// express.json() middleware to parse JSON bodies.
195-
// It must be used before the POST /mcp route but after the GET /sse route :shrug:
169+
// It must be used before the POST / route but after the GET /sse route :shrug:
196170
app.use(express.json());
197171
app.post(Routes.MCP, async (req: Request, res: Response) => {
198172
log.info('Received MCP request:', req.body);

0 commit comments

Comments
 (0)