Skip to main content
Glama

LINE Bot MCP Server

by tndfame
tmp_k.tsx5.25 kB
"use client"; import { useEffect, useMemo, useState } from "react"; type FileItem = string; export default function KnowledgePage() { const [files, setFiles] = useState<FileItem[]>([]); const [selected, setSelected] = useState<string>(""); const [pathInput, setPathInput] = useState<string>(""); const [content, setContent] = useState<string>(""); const [out, setOut] = useState<string>(""); const [error, setError] = useState<string>(""); const [loading, setLoading] = useState(false); async function loadFiles() { setError(""); try { const res = await fetch(`/api/files`); const data = await res.json(); const list = Array.isArray(data?.files) ? (data.files as string[]) : []; setFiles(list); if (!selected && list.length) setSelected(list[0]); } catch (e: any) { setError(e?.message || String(e)); } } async function loadFile(p: string) { setError(""); if (!p) return; try { const res = await fetch(`/api/file?path=${encodeURIComponent(p)}`); const data = await res.json(); if (data?.content != null) { setPathInput(p); setContent(data.content); } else { setContent(""); } } catch (e: any) { setError(e?.message || String(e)); } } async function saveFile() { setLoading(true); setError(""); setOut(""); try { if (!pathInput) throw new Error("Please enter a docs/*.md path"); const res = await fetch(`/api/file`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ path: pathInput, content }), }); const data = await res.json(); if (res.ok) { setOut(`Saved: ${data?.path}`); await loadFiles(); } else { throw new Error(data?.error || "Failed to save"); } } catch (e: any) { setError(e?.message || String(e)); } finally { setLoading(false); } } useEffect(() => { loadFiles(); }, []); useEffect(() => { if (selected) loadFile(selected); }, [selected]); const fileOptions = useMemo( () => files.map(f => (<option key={f} value={f}>{f}</option>)), [files], ); return ( <section className="card panel" style={{ width: '100%' }}> <div className="section"> <div className="field"> <label>Docs Files</label> <select value={selected} onChange={e => setSelected(e.target.value)} size={8} style={{ width: "100%", maxWidth: 480 }}> {fileOptions} </select> <div className="row" style={{ marginTop: 8 }}> <button className="btn secondary" onClick={async () => { try { const p = window.prompt( 'New file path (under docs/data-learning), e.g. "docs/data-learning/new-note.md"', 'docs/data-learning/new-note.md', ); if (!p) return; const pathOk = p.startsWith('docs/data-learning/') && p.toLowerCase().endsWith('.md'); const invalid = /[\\\0\r\n]/.test(p) || p.includes('..'); if (!pathOk || invalid) { alert('Invalid path. Must start with "docs/data-learning/" and end with .md, no \'..\' or backslashes.'); return; } const initial = `# ${p.split('/').pop() || 'New Note'}\n\nCreated: ${new Date().toISOString()}\n`; const res = await fetch(`/api/file`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path: p, content: initial }), }); const data = await res.json(); if (!res.ok || data?.error) throw new Error(data?.error || `HTTP ${res.status}`); await loadFiles(); setSelected(p); await loadFile(p); } catch (e: any) { setError(e?.message || String(e)); } }} >New file</button> </div> </div> <div className="field"> <label>Path</label> <input value={pathInput} onChange={e => setPathInput(e.target.value)} placeholder="docs/data-learning/knowledge.md or docs/ai-presets/my-knowledge.md" style={{ width: "100%" }} /> </div> <div className="field"> <label>Content (Markdown)</label> <textarea value={content} onChange={e => setContent(e.target.value)} style={{ minHeight: 360 }} /> </div> <div className="row"> <button className="btn" onClick={saveFile} disabled={loading}>{loading ? "Saving..." : "Save"}</button> {error ? <div className="muted">Error: {error}</div> : null} {out ? <div className="muted">{out}</div> : null} </div> </div> </section> ); }

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/tndfame/mcp_management'

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