Skip to main content
Glama

Article Manager MCP Server

by joelmnz
App.tsx•4.33 kB
import React, { useState, useEffect } from 'react'; import { createRoot } from 'react-dom/client'; import { Login } from './components/Login'; import { Header } from './components/Header'; import { Home } from './pages/Home'; import { ArticleView } from './pages/ArticleView'; import { ArticleEdit } from './pages/ArticleEdit'; import { RAGStatus } from './pages/RAGStatus'; import './styles/main.css'; type Route = | { type: 'home' } | { type: 'article'; filename: string } | { type: 'edit'; filename: string } | { type: 'new' } | { type: 'rag-status' }; function App() { const [token, setToken] = useState<string | null>(null); const [theme, setTheme] = useState<'light' | 'dark'>('dark'); const [route, setRoute] = useState<Route>({ type: 'home' }); const [intendedRoute, setIntendedRoute] = useState<Route | null>(null); useEffect(() => { // Load saved token and theme const savedToken = localStorage.getItem('auth_token'); const savedTheme = localStorage.getItem('theme') as 'light' | 'dark' | null; if (savedToken) { setToken(savedToken); } if (savedTheme) { setTheme(savedTheme); } // Parse initial route from URL const path = window.location.pathname; const parsedRoute = parseRoute(path); if (!savedToken && parsedRoute.type !== 'home') { setIntendedRoute(parsedRoute); } else { setRoute(parsedRoute); } // Handle browser back/forward window.addEventListener('popstate', () => { setRoute(parseRoute(window.location.pathname)); }); // Register service worker for PWA support if ('serviceWorker' in navigator) { navigator.serviceWorker .register('/sw.js') .then((registration) => { console.log('Service Worker registered:', registration); }) .catch((error) => { console.error('Service Worker registration failed:', error); }); } }, []); useEffect(() => { document.documentElement.setAttribute('data-theme', theme); }, [theme]); const parseRoute = (path: string): Route => { if (path === '/' || path === '') { return { type: 'home' }; } if (path === '/rag-status') { return { type: 'rag-status' }; } if (path.startsWith('/article/')) { const filename = path.replace('/article/', ''); return { type: 'article', filename }; } if (path.startsWith('/edit/')) { const filename = path.replace('/edit/', ''); return { type: 'edit', filename }; } if (path === '/new') { return { type: 'new' }; } return { type: 'home' }; }; const navigate = (path: string) => { const newRoute = parseRoute(path); setRoute(newRoute); window.history.pushState({}, '', path); }; const handleLogin = (newToken: string) => { setToken(newToken); localStorage.setItem('auth_token', newToken); // Navigate to intended route if exists if (intendedRoute) { setRoute(intendedRoute); setIntendedRoute(null); } }; const handleLogout = () => { setToken(null); localStorage.removeItem('auth_token'); setRoute({ type: 'home' }); navigate('/'); }; const handleThemeToggle = () => { const newTheme = theme === 'dark' ? 'light' : 'dark'; setTheme(newTheme); localStorage.setItem('theme', newTheme); }; if (!token) { return <Login onLogin={handleLogin} />; } return ( <div className="app"> <Header theme={theme} onThemeToggle={handleThemeToggle} onLogout={handleLogout} /> <main className="main"> {route.type === 'home' && ( <Home token={token} onNavigate={navigate} /> )} {route.type === 'rag-status' && ( <RAGStatus token={token} onNavigate={navigate} /> )} {route.type === 'article' && ( <ArticleView filename={route.filename} token={token} onNavigate={navigate} /> )} {route.type === 'edit' && ( <ArticleEdit filename={route.filename} token={token} onNavigate={navigate} /> )} {route.type === 'new' && ( <ArticleEdit token={token} onNavigate={navigate} /> )} </main> </div> ); } const root = createRoot(document.getElementById('root')!); root.render(<App />);

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/joelmnz/mcp-markdown-manager'

If you have feedback or need assistance with the MCP directory API, please join our Discord server