From ab15a65585ee253d799ae32d80e7c705541d0906 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 9 May 2026 21:15:03 +0000 Subject: [PATCH] simplify: unify 405 handlers, fix double-read in renameRundown, guard mcpClientConfig - mcp.router.ts: extract identical GET/DELETE 405 responses into methodNotAllowed - mcp.service.ts: pass the already-patched rundown object to initRundown instead of re-fetching it from the data provider - McpSection.tsx: compute mcpClientConfig only when mcpEndpointUrl is truthy https://claude.ai/code/session_01U24MeuUacYXeQhbX3tatEe --- .../app-settings/panel/feature-panel/McpSection.tsx | 4 +++- apps/server/src/api-mcp/mcp.router.ts | 12 +++++------- apps/server/src/api-mcp/mcp.service.ts | 5 +++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/client/src/features/app-settings/panel/feature-panel/McpSection.tsx b/apps/client/src/features/app-settings/panel/feature-panel/McpSection.tsx index ebff5a1c2..dcbe7d4be 100644 --- a/apps/client/src/features/app-settings/panel/feature-panel/McpSection.tsx +++ b/apps/client/src/features/app-settings/panel/feature-panel/McpSection.tsx @@ -25,7 +25,9 @@ export default function McpSection() { }); }, [infoData]); - const mcpClientConfig = JSON.stringify({ mcpServers: { ontime: { url: mcpEndpointUrl } } }, null, 2); + const mcpClientConfig = mcpEndpointUrl + ? JSON.stringify({ mcpServers: { ontime: { url: mcpEndpointUrl } } }, null, 2) + : ''; return ( diff --git a/apps/server/src/api-mcp/mcp.router.ts b/apps/server/src/api-mcp/mcp.router.ts index 250207065..08f3f0344 100644 --- a/apps/server/src/api-mcp/mcp.router.ts +++ b/apps/server/src/api-mcp/mcp.router.ts @@ -1,6 +1,6 @@ import type { IncomingMessage, ServerResponse } from 'node:http'; -import express from 'express'; +import express, { type Request, type Response } from 'express'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { createMcpServer } from './mcp.server.js'; @@ -22,10 +22,8 @@ mcpRouter.post('/', async (req, res) => { // Stateless mode: GET (SSE) and DELETE (session teardown) are not applicable. // All MCP interactions happen via POST in a single request/response cycle. -mcpRouter.get('/', (_req, res) => { - res.status(405).json({ jsonrpc: '2.0', error: { code: -32000, message: 'Method not allowed.' }, id: null }); -}); +const methodNotAllowed = (_req: Request, res: Response) => + void res.status(405).json({ jsonrpc: '2.0', error: { code: -32000, message: 'Method not allowed.' }, id: null }); -mcpRouter.delete('/', (_req, res) => { - res.status(405).json({ jsonrpc: '2.0', error: { code: -32000, message: 'Method not allowed.' }, id: null }); -}); +mcpRouter.get('/', methodNotAllowed); +mcpRouter.delete('/', methodNotAllowed); diff --git a/apps/server/src/api-mcp/mcp.service.ts b/apps/server/src/api-mcp/mcp.service.ts index 7b219624f..2addd3968 100644 --- a/apps/server/src/api-mcp/mcp.service.ts +++ b/apps/server/src/api-mcp/mcp.service.ts @@ -15,9 +15,10 @@ export async function renameRundown(id: string, title: string) { const dataProvider = getDataProvider(); const rundown = dataProvider.getRundown(id); if (!rundown) throw new Error(`Rundown ${id} not found`); - await dataProvider.setRundown(id, { ...rundown, title }); + const updated = { ...rundown, title }; + await dataProvider.setRundown(id, updated); if (id === getCurrentRundown().id) { - await initRundown(dataProvider.getRundown(id), dataProvider.getCustomFields()); + await initRundown(updated, dataProvider.getCustomFields()); } return rundownListResponse(); }