screenpipe/screenpipe · warning
404 not found
Error message
404 not found
What it means
The ACP screenpipe-tools MCP server only accepts requests whose URL starts with /mcp (plus /health). Anything else gets a bare HTTP 404 with an empty body. This is a path/router mismatch, not an MCP protocol error — the request never reached the MCP handler.
Source
Thrown at crates/screenpipe-core/assets/acp/screenpipe-tools.mjs:1384
}
// Stateless Streamable-HTTP: each POST /mcp carries one JSON-RPC request (or a
// batch) and gets a single JSON response. None of these tools stream, so no SSE
// channel is opened. Bound to loopback with an Origin check per the MCP spec's
// DNS-rebinding guidance; no session id (stateless), which every ACP harness we
// target tolerates.
const LOOPBACK_ORIGIN = /^https?:\/\/(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i;
function startHttpServer(port) {
const server = createServer((req, res) => {
const url = req.url || "/";
if (req.method === "GET" && url.startsWith("/health")) {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ ok: true, server: SERVER_INFO }));
return;
}
if (!url.startsWith("/mcp")) {
res.writeHead(404).end();
return;
}
const origin = req.headers["origin"];
if (origin && !LOOPBACK_ORIGIN.test(origin)) {
res.writeHead(403).end();
return;
}
if (req.method !== "POST") {
res.writeHead(405, { Allow: "POST" }).end();
return;
}
let body = "";
req.setEncoding("utf-8");
req.on("data", (chunk) => {
body += chunk;
if (body.length > 4_000_000) req.destroy();
});
req.on("end", async () => {View on GitHub (pinned to 4ebf712990)
Solutions
- Point the MCP client at the exact path /mcp on the server port
- Verify with GET /health first — it returns 200 {ok:true,server:SERVER_INFO} to confirm you reached the right server
- Remove any path prefixes added by reverse proxies or client config
- Check SERVER_INFO/health output to confirm the expected endpoint layout
Example fix
// before
const server = new MCPClient({ url: 'http://127.0.0.1:9000/api/mcp' });
// after
const server = new MCPClient({ url: 'http://127.0.0.1:9000/mcp' }); Defensive patterns
Strategy: validation
Validate before calling
function assertMcpUrl(u) {
const { pathname } = new URL(u);
if (pathname !== '/mcp') throw new Error(`MCP server expects path /mcp, got ${pathname}`);
return u;
}
// preflight
await fetch(new URL('/health', base)).then(r => r.json()); // must return {ok:true,...} Type guard
function isMcpBase(u) {
try { return new URL(u).pathname === '/mcp'; } catch { return false; }
} Try / catch
const res = await fetch(mcpUrl, init);
if (res.status === 404) {
throw new Error(`MCP endpoint 404 — use /mcp (health check: GET /health)`);
} Prevention
- Configure MCP clients with the exact base path /mcp, no trailing extras
- Run GET /health as a preflight to confirm the right server/port
- Avoid proxy rewrites that alter the /mcp prefix
- Store the MCP URL in config, not scattered literals
When it happens
Trigger: POSTing to a path like / or /tools or /api/mcp; misconfigured MCP client baseUrl that includes/excludes a path prefix incorrectly; requesting /mcp/ with tools that build URLs differently; hitting the wrong port where another route layout is expected.
Common situations: MCP client configured with server URL http://127.0.0.1:PORT/mcp/ extra-slash variants or a legacy /jsonrpc path; dev proxy stripping or adding prefixes; client pointed at /health by mistake.
Related errors
- not found
- server_id is required
- tool is required
- sp_mcp_call failed (${res.status}): ${bodyText.slice(0, 800)
- MCP tool "${tool}" on server "${serverId}" reported an error
AI-assisted analysis of screenpipe/screenpipe@4ebf712990 (2026-09-01).
Data as JSON: /api/errors/4b1b03a563a3562a.
Report an issue: GitHub.