fix: align MCP server schema with memento-note + per-request user isolation
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 12s

- Remove `embedding` column from MCP Note model (dropped by migration 20260425120000)
- Add missing columns: trashedAt, dismissedFromRecent, contentUpdatedAt, cardSizeMode
- Add NoteEmbedding model and Label.notebook relation
- Use AsyncLocalStorage to pass authenticated userId from API key to tool handlers
- Enable SSE mode and auth in docker-compose for N8N integration

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 14:44:01 +02:00
parent 9779dd7a79
commit 2f1837560b
5 changed files with 63 additions and 18 deletions

View File

@@ -18,6 +18,7 @@ import {
ListToolsRequestSchema,
McpError,
} from '@modelcontextprotocol/sdk/types.js';
import { requestContext } from './request-context.js';
// ─── Configuration ─────────────────────────────────────────────────────────
@@ -603,22 +604,30 @@ const toolDefinitions = [
* @param {string} [options.appBaseUrl] - Optional base URL of the Next.js app for AI API calls
*/
export function registerTools(server, prisma, options = {}) {
const { userId = null, appBaseUrl = null } = options;
const { appBaseUrl = null } = options;
// Resolve userId per-request from AsyncLocalStorage (set by auth middleware)
const getResolvedUserId = () => {
const store = requestContext.getStore();
return store?.userId || null;
};
// Fallback: auto-detect first user when no auth context
let fallbackUserId = null;
let fallbackPromise = null;
// Resolve userId: if not provided, auto-detect the first user
let resolvedUserId = userId;
let userIdPromise = null;
const ensureUserId = async () => {
if (resolvedUserId) return resolvedUserId;
if (userIdPromise) return userIdPromise;
userIdPromise = prisma.user.findFirst({ select: { id: true } }).then(u => {
if (u) resolvedUserId = u.id;
return resolvedUserId;
const fromContext = getResolvedUserId();
if (fromContext) return fromContext;
if (fallbackUserId) return fallbackUserId;
if (fallbackPromise) return fallbackPromise;
fallbackPromise = prisma.user.findFirst({ select: { id: true } }).then(u => {
if (u) fallbackUserId = u.id;
return fallbackUserId;
});
return userIdPromise;
return fallbackPromise;
};
// ── List Tools ────────────────────────────────────────────────────────────
@@ -629,6 +638,7 @@ export function registerTools(server, prisma, options = {}) {
// ── Call Tools ────────────────────────────────────────────────────────────
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
const resolvedUserId = getResolvedUserId();
try {
switch (name) {