mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 22:39:40 +02:00
Implement actual sync_changes reads and writes for MCP tool calls:
- sync-db.ts: Connection to mana_sync DB, RLS-scoped withUser(),
readLatestRecords() for replaying sync state, writeRecord() for
creating sync_changes entries
- executor.ts: 10 tool handlers implemented:
- Reads: list_tasks, get_task_stats, list_notes, get_todays_events,
get_contacts, get_habits
- Writes: create_task, complete_task, create_note, create_contact
- Remaining tools return helpful "not yet implemented" message
- server.ts: userId from auth context bound into MCP session via closure
- index.ts: typed Hono app with AuthVariables
Write pattern matches mana-ai: INSERT into sync_changes with
actor={kind:'system', source:'mcp-tool'}, client_id='mcp-server'.
Records appear on user devices on next sync cycle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
82 lines
3.5 KiB
TypeScript
82 lines
3.5 KiB
TypeScript
/**
|
|
* Mana Unified API Server
|
|
*
|
|
* Consolidates all app compute servers into one Hono/Bun process.
|
|
* Each module registers its routes under /api/v1/{module}/*.
|
|
*/
|
|
|
|
import { Hono } from 'hono';
|
|
import { cors } from 'hono/cors';
|
|
import {
|
|
authMiddleware,
|
|
healthRoute,
|
|
errorHandler,
|
|
notFoundHandler,
|
|
rateLimitMiddleware,
|
|
type AuthVariables,
|
|
} from '@mana/shared-hono';
|
|
|
|
// MCP server
|
|
import { handleMcpRequest } from './mcp/server';
|
|
|
|
// Module routes
|
|
import { calendarRoutes } from './modules/calendar/routes';
|
|
import { contactsRoutes } from './modules/contacts/routes';
|
|
import { musicRoutes } from './modules/music/routes';
|
|
import { chatRoutes } from './modules/chat/routes';
|
|
import { contextRoutes } from './modules/context/routes';
|
|
import { pictureRoutes } from './modules/picture/routes';
|
|
import { storageRoutes } from './modules/storage/routes';
|
|
import { todoRoutes } from './modules/todo/routes';
|
|
import { plantsRoutes } from './modules/plants/routes';
|
|
import { foodRoutes } from './modules/food/routes';
|
|
import { guidesRoutes } from './modules/guides/routes';
|
|
import { moodlitRoutes } from './modules/moodlit/routes';
|
|
import { newsRoutes } from './modules/news/routes';
|
|
import { newsResearchRoutes } from './modules/news-research/routes';
|
|
import { tracesRoutes } from './modules/traces/routes';
|
|
import { presiRoutes } from './modules/presi/routes';
|
|
import { researchRoutes } from './modules/research/routes';
|
|
import { whoRoutes } from './modules/who/routes';
|
|
|
|
const PORT = parseInt(process.env.PORT || '3060', 10);
|
|
const CORS_ORIGINS = (process.env.CORS_ORIGINS || 'http://localhost:5173').split(',');
|
|
|
|
const app = new Hono<{ Variables: AuthVariables }>();
|
|
|
|
// ─── Global Middleware ──────────────────────────────────────
|
|
app.onError(errorHandler);
|
|
app.notFound(notFoundHandler);
|
|
app.use('*', cors({ origin: CORS_ORIGINS, credentials: true }));
|
|
app.route('/health', healthRoute('mana-api'));
|
|
app.use('/api/*', rateLimitMiddleware({ max: 200, windowMs: 60_000 }));
|
|
app.use('/api/*', authMiddleware());
|
|
|
|
// ─── MCP Endpoint ──────────────────────────────────────────
|
|
// Streamable HTTP transport: POST (messages), GET (SSE stream), DELETE (close)
|
|
app.all('/api/v1/mcp', (c) => handleMcpRequest(c.req.raw, c.get('userId')));
|
|
|
|
// ─── Module Routes ──────────────────────────────────────────
|
|
app.route('/api/v1/calendar', calendarRoutes);
|
|
app.route('/api/v1/contacts', contactsRoutes);
|
|
app.route('/api/v1/music', musicRoutes);
|
|
app.route('/api/v1/chat', chatRoutes);
|
|
app.route('/api/v1/context', contextRoutes);
|
|
app.route('/api/v1/picture', pictureRoutes);
|
|
app.route('/api/v1/storage', storageRoutes);
|
|
app.route('/api/v1/todo', todoRoutes);
|
|
app.route('/api/v1/plants', plantsRoutes);
|
|
app.route('/api/v1/food', foodRoutes);
|
|
app.route('/api/v1/guides', guidesRoutes);
|
|
app.route('/api/v1/moodlit', moodlitRoutes);
|
|
app.route('/api/v1/news', newsRoutes);
|
|
app.route('/api/v1/news-research', newsResearchRoutes);
|
|
app.route('/api/v1/traces', tracesRoutes);
|
|
app.route('/api/v1/presi', presiRoutes);
|
|
app.route('/api/v1/research', researchRoutes);
|
|
app.route('/api/v1/who', whoRoutes);
|
|
|
|
// ─── Server Info ────────────────────────────────────────────
|
|
console.log(`mana-api starting on port ${PORT}...`);
|
|
|
|
export default { port: PORT, fetch: app.fetch };
|