#!/usr/bin/env node // ============================================================ // Attic Standard MCP Server — Entry Point // ============================================================ // Dual transport: stdio (local) and Streamable HTTP (remote). // Set TRANSPORT=http for HTTP mode, default is stdio. // ============================================================ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import express from "express"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import { createServer } from "./server.js"; import { SERVER_NAME, SERVER_VERSION, ICON_PATH, SITE } from "./config.js"; // ---------------------------------------------------------- // stdio transport (for Cursor, Claude Desktop, etc.) // ---------------------------------------------------------- async function runStdio(): Promise { const server = createServer(); const transport = new StdioServerTransport(); await server.connect(transport); console.error("Attic Standard MCP Server running via stdio"); } // ---------------------------------------------------------- // Streamable HTTP transport (for hosted / remote access) // ---------------------------------------------------------- async function runHTTP(): Promise { const app = express(); app.use(express.json()); // CORS — allow browser-based MCP clients and test tools app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Content-Type'); res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS'); if (req.method === 'OPTIONS') { res.sendStatus(200); return; } next(); }); // Icon: the Attic Standard mark, shipped with the server so MCP // clients that look for a favicon on the server address find one. let icon: Buffer | null = null; try { icon = readFileSync(join(process.cwd(), "assets", "icon.png")); } catch (err) { console.error("MCP: icon file not found:", err); } const sendIcon = (_req: express.Request, res: express.Response) => { if (!icon) return res.redirect(302, `${SITE}/favicon.ico`); res.set("Content-Type", "image/png").set("Cache-Control", "public, max-age=86400").send(icon); }; app.get([ICON_PATH, "/favicon.ico", "/apple-touch-icon.png"], sendIcon); // Root: a minimal page so browsers and clients see the name and icon. app.get("/", (_req, res) => { res .type("html") .send( `Attic Standard MCP

Attic Standard MCP server. Connect your MCP client to /mcp. atticstandard.com/mcp

` ); }); // Health check app.get("/health", (_req, res) => { res.json({ status: "ok", server: SERVER_NAME, version: SERVER_VERSION, }); }); // MCP endpoint — stateless mode (new transport per request) app.post("/mcp", async (req, res) => { const server = createServer(); const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, // stateless enableJsonResponse: true, }); res.on("close", () => { transport.close(); }); await server.connect(transport); await transport.handleRequest(req, res, req.body); }); // Handle GET and DELETE for MCP protocol completeness app.get("/mcp", (_req, res) => { res.status(405).json({ error: "Method Not Allowed. Use POST for MCP requests.", }); }); app.delete("/mcp", (_req, res) => { res.status(405).json({ error: "Method Not Allowed. Stateless server — no sessions to delete.", }); }); const port = parseInt(process.env.PORT || "3000", 10); app.listen(port, () => { console.error(`Attic Standard MCP Server running on http://localhost:${port}/mcp`); console.error(`Health check: http://localhost:${port}/health`); }); } // ---------------------------------------------------------- // Transport selection // ---------------------------------------------------------- const transport = process.env.TRANSPORT || "stdio"; if (transport === "http") { runHTTP().catch((error) => { console.error("Attic Standard MCP Server HTTP error:", error); process.exit(1); }); } else { runStdio().catch((error) => { console.error("Attic Standard MCP Server stdio error:", error); process.exit(1); }); }