Tool reference
Lookout exposes five MCP tools over a single HTTP endpoint. Reads answer from your connected meetings; writes change your own memory and always confirm first. Every tool re-derives your identity from your OAuth token — never from an argument you pass.
Endpoint: https://lookout.neurobaselabs.com/mcp · Auth: OAuth 2.1 + PKCE
| Tool | Purpose |
|---|---|
recall | Answer a natural-language question from your memory, with sources. |
search_meetings | Semantic + keyword search across your meetings; returns ranked matches with snippets. |
list_meetings | List recent meetings, newest first — the fastest way to confirm wiring. |
add_memory | Add a decision, commitment, person, or note to your memory (confirmed write). |
edit_memory | Correct or update an existing memory entry you own (confirmed write). |
Typed signatures
Types are shown in TypeScript notation for readability; the wire format is JSON over MCP. ? marks an optional parameter. All dates are ISO 8601.
// recall — the primary read. Natural-language question in, source-traced answer out.
// Runs on YOUR Claude tokens via MCP; we never see the conversation.
recall(
query: string,
since?: string, // ISO date — only consider meetings on/after this date
until?: string, // ISO date — only consider meetings on/before this date
sources?: Source[] // restrict to specific notetakers; default = all connected
): {
answer: string; // the synthesized answer
decisions: Decision[]; // decisions grounding the answer (may be empty)
commitments: Commitment[]; // action items tied to the answer (may be empty)
citations: Citation[]; // every claim traces to at least one of these
}
// search_meetings — ranked retrieval when you want the meetings, not a synthesized answer.
search_meetings(
query: string,
limit?: number, // default 10, max 50
since?: string, // ISO date lower bound
until?: string, // ISO date upper bound
sources?: Source[] // restrict to specific notetakers; default = all connected
): {
results: MeetingMatch[]; // ranked; each has meeting_id, title, date, source, score, snippet
total: number; // total matches before limit
}
// list_meetings — newest-first listing. Best first call to confirm the connection.
list_meetings(
limit?: number, // default 20, max 100
since?: string, // ISO date — only meetings on/after this date
source?: Source // filter to a single source
): {
meetings: MeetingRef[]; // { meeting_id, title, date, source, participant_count, ingested }
next_cursor?: string; // present only if more results exist
}
// add_memory — write a new entry to YOUR memory. Human-in-the-loop:
// returns a preview and requires confirmation before it commits.
add_memory(
kind: "decision" | "commitment" | "person" | "note",
content: string,
meeting_id?: string, // attach to a specific meeting for context
owner?: string, // for a commitment — who owns it
due?: string // ISO date — only meaningful when kind = "commitment"
): {
status: "pending_confirmation" | "committed";
entry: MemoryEntry; // the entry as it will be / was stored
}
// edit_memory — update an existing entry you own. Also confirmed before it commits.
edit_memory(
entry_id: string,
content?: string, // new content (omit to leave unchanged)
owner?: string, // reassign a commitment's owner
due?: string, // new due date for a commitment
status?: "open" | "done" | "cancelled" // commitment status
): {
status: "pending_confirmation" | "committed";
entry: MemoryEntry; // the entry after the proposed edit
}Shared shapes
type Source = "fireflies" | "granola" | "otter" | "calendar";
type Citation = {
meeting_id: string;
meeting_title: string;
speaker: string | null; // who said it, when attributable
date: string; // ISO date of the meeting
source: Source; // which notetaker it came from
quote?: string; // verbatim supporting snippet, when available
};
type Decision = {
statement: string;
decided_by: string | null; // person / role as captured
meeting_id: string;
};
type Commitment = {
entry_id: string;
who: string;
what: string;
due: string | null; // ISO date, or null if none was set
status: "open" | "done" | "cancelled";
};
type MeetingRef = {
meeting_id: string;
title: string;
date: string; // ISO date
source: Source;
participant_count: number;
ingested: boolean; // false while a backfill is still threading
};
type MemoryEntry = {
entry_id: string;
kind: "decision" | "commitment" | "person" | "note";
content: string;
meeting_id: string | null;
};Resolution & permission order
Every call resolves in a fixed order, and fails closed rather than guessing:
- Identity from the token. Your identity is derived from the OAuth token on every call — never from a tool argument. Any user identifier in the arguments is ignored; the token wins.
- Scope at the database. The resolved identity sets the per-user Row-Level Security scope. Every read and write is confined to your own rows. Reaching another user's memory isn't denied at the app layer — there is no query path to it at the data layer.
- Writes confirm first.
add_memoryandedit_memoryreturnpending_confirmationwith a preview; nothing commits until you approve. No silent writes, ever. - Fail closed. A missing, expired, or revoked token returns an auth error — never a partial or cross-user result. A call that can't be satisfied within your scope returns an explicit empty result or error; it does not widen the search.
Debugging
Inspect the raw MCP surface outside Claude Code with the reference inspector:
npx @modelcontextprotocol/inspector https://lookout.neurobaselabs.com/mcp
Start with list_meetings to confirm the connection is live and your ingestion has landed. If your meetings come back, recall and search_meetingsresolve against the same memory. If the list is empty right after connecting, the issue is ingestion (a source still threading), not the tool wiring — give it a moment and retry.
Security candor
Lookout is in private beta, and we'd rather tell you what's true than what sounds finished. The tools above are the entire surface — read your memory, search it, list it, and (with confirmation) write to it. There is no tool that returns your source credentials and none that reads another user's data, because neither capability exists in the surface — not merely because it's disallowed. Your source credentials (Fireflies, Otter, calendar tokens) are envelope-encrypted, used only by the backend ingester, and are never exposed to the tool surface or rendered back to you. These tools read and write your memory— the structured decisions, commitments, people, and dates we threaded — not your raw source accounts. Recall runs on your own Claude tokens; we never receive or log your Claude conversation. If any of this changes, this page changes with it.