Reference

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

ToolPurpose
recallAnswer a natural-language question from your memory, with sources.
search_meetingsSemantic + keyword search across your meetings; returns ranked matches with snippets.
list_meetingsList recent meetings, newest first — the fastest way to confirm wiring.
add_memoryAdd a decision, commitment, person, or note to your memory (confirmed write).
edit_memoryCorrect 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:

  1. 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.
  2. 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.
  3. Writes confirm first. add_memory and edit_memory return pending_confirmation with a preview; nothing commits until you approve. No silent writes, ever.
  4. 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.