feat: add MCP server for AI agent integration

Adds a Streamable HTTP MCP server at /mcp that exposes 19 tools
covering rundown entries, rundown management, runtime state, project
info, automations, and custom fields. Includes Bearer token auth
support and a UI card in Settings > Sharing showing the endpoint URL
and Claude Desktop config.

https://claude.ai/code/session_01U24MeuUacYXeQhbX3tatEe
This commit is contained in:
Claude
2026-04-22 18:24:17 +00:00
committed by Carlos Valente
parent 41a09bf5c3
commit ac3694ce4d
6 changed files with 809 additions and 2 deletions
@@ -1,5 +1,10 @@
import { useEffect, useState } from 'react';
import useScrollIntoView from '../../../../common/hooks/useScrollIntoView';
import { isOntimeCloud } from '../../../../externals';
import { generateUrl } from '../../../../common/api/session';
import CopyTag from '../../../../common/components/copy-tag/CopyTag';
import useInfo from '../../../../common/hooks-query/useInfo';
import { isOntimeCloud, serverURL } from '../../../../externals';
import GenerateLinkFormExport from '../../../sharing/GenerateLinkFormExport';
import type { PanelBaseProps } from '../../panel-list/PanelList';
import * as Panel from '../../panel-utils/PanelUtils';
@@ -11,6 +16,30 @@ export default function FeaturePanel({ location }: PanelBaseProps) {
const presetsRef = useScrollIntoView<HTMLDivElement>('presets', location);
const linkRef = useScrollIntoView<HTMLDivElement>('link', location);
const reportRef = useScrollIntoView<HTMLDivElement>('report', location);
const mcpRef = useScrollIntoView<HTMLDivElement>('mcp', location);
const { data: infoData } = useInfo();
const [mcpEndpointUrl, setMcpEndpointUrl] = useState('');
useEffect(() => {
const baseUrl = isOntimeCloud
? serverURL
: infoData.networkInterfaces.length > 0
? `http://${infoData.networkInterfaces[0].address}:${infoData.serverPort}`
: serverURL;
generateUrl({ baseUrl, path: '/mcp', authenticate: true, lockConfig: false, lockNav: false })
.then(setMcpEndpointUrl)
.catch(() => {
setMcpEndpointUrl(`${baseUrl}/mcp`);
});
}, [infoData]);
const claudeDesktopConfig = JSON.stringify(
{ mcpServers: { ontime: { url: mcpEndpointUrl } } },
null,
2,
);
return (
<>
@@ -33,6 +62,32 @@ export default function FeaturePanel({ location }: PanelBaseProps) {
</Panel.Card>
</Panel.Section>
</div>
<div ref={mcpRef}>
<Panel.Section>
<Panel.Card>
<Panel.SubHeader>MCP Server (AI Agent Integration)</Panel.SubHeader>
<Panel.Paragraph>
Connect AI agents (e.g. Claude Desktop) to Ontime via the Model Context Protocol endpoint.
</Panel.Paragraph>
<Panel.Divider />
<Panel.Field
title='MCP Endpoint URL'
description='Use this URL in your MCP client configuration'
/>
{mcpEndpointUrl && (
<CopyTag copyValue={mcpEndpointUrl}>{mcpEndpointUrl}</CopyTag>
)}
<Panel.Divider />
<Panel.Field
title='Claude Desktop config'
description='Paste this into your claude_desktop_config.json under "mcpServers"'
/>
{mcpEndpointUrl && (
<CopyTag copyValue={claudeDesktopConfig}>{claudeDesktopConfig}</CopyTag>
)}
</Panel.Card>
</Panel.Section>
</div>
<div ref={reportRef}>
<ReportSettings />
</div>