HeroMind MCP API Reference

Overview

The HeroMind MCP (Model Context Protocol) server implements the standard MCP specification to provide secure, authenticated access to task management functionality. This document provides detailed technical reference for developers and integrators.

Base URL

https://your-supabase-project.supabase.co/functions/v1/mcp-server

Replace your-supabase-project with your actual Supabase project identifier.

Authentication

All requests (except initialize) require Bearer token authentication:

Authorization: Bearer <your-mcp-token>

Tokens are generated through the HeroMind admin panel and include:

  • SHA-256 hashed storage for security
  • Configurable expiration dates
  • Permission-based access control
  • Rate limiting settings

Protocol Specification

The server implements MCP version 2024-11-05 and follows the JSON-RPC 2.0 specification.

Request Format

All requests must be POST requests with Content-Type: application/json:

{
  "jsonrpc": "2.0",
  "method": "<method-name>",
  "params": { ... },
  "id": "<unique-request-id>"
}

Response Format

Successful responses:

{
  "jsonrpc": "2.0",
  "result": { ... },
  "id": "<request-id>"
}

Error responses:

{
  "jsonrpc": "2.0",
  "error": {
    "code": <error-code>,
    "message": "<error-message>",
    "data": { ... }
  },
  "id": "<request-id>"
}

Endpoints

Initialize

Establishes the MCP connection and exchanges capability information.

Method: initialize Authentication: Not required Rate Limited: No

Request

{
  "jsonrpc": "2.0",
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {}
  },
  "id": 1
}

Response

{
  "jsonrpc": "2.0",
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "experimental": {},
      "sampling": {}
    },
    "serverInfo": {
      "name": "HeroMind Task Manager",
      "version": "1.0.0"
    }
  },
  "id": 1
}

List Tools

Returns all available tools that can be called through the MCP interface.

Method: tools/list Authentication: Required Rate Limited: Yes

Request

{
  "jsonrpc": "2.0",
  "method": "tools/list",
  "params": {},
  "id": 2
}

Response

{
  "jsonrpc": "2.0",
  "result": {
    "tools": [
      {
        "name": "create_personal_task",
        "description": "Create a new personal task in HeroMind",
        "inputSchema": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "description": "Task name or description (required)",
              "minLength": 1,
              "maxLength": 500
            },
            "start_date": {
              "type": "string",
              "format": "date-time",
              "description": "When the task should start (optional, ISO 8601 format)"
            },
            "due_date": {
              "type": "string",
              "format": "date-time",
              "description": "When the task is due (optional, ISO 8601 format)"
            }
          },
          "required": ["name"]
        }
      },
      {
        "name": "create_work_task",
        "description": "Create a new work-related task in HeroMind",
        "inputSchema": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "description": "Task name or description (required)",
              "minLength": 1,
              "maxLength": 500
            },
            "start_date": {
              "type": "string",
              "format": "date-time",
              "description": "When the task should start (optional, ISO 8601 format)"
            },
            "due_date": {
              "type": "string",
              "format": "date-time",
              "description": "When the task is due (optional, ISO 8601 format)"
            }
          },
          "required": ["name"]
        }
      }
    ]
  },
  "id": 2
}

Call Tool

Executes a specific tool with provided arguments.

Method: tools/call Authentication: Required Rate Limited: Yes

Request

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "create_personal_task",
    "arguments": {
      "name": "Buy groceries for the week",
      "due_date": "2024-01-15T18:00:00Z"
    }
  },
  "id": 3
}

Response (Success)

{
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "✅ Successfully created personal task: \"Buy groceries for the week\"\n\n📋 Task ID: 123e4567-e89b-12d3-a456-426614174000\n🏷️ Category: personal\n📅 Due Date: Jan 15, 2024\n⏰ Created: Jan 10, 2024, 10:30 AM\n\nYour task has been added to HeroMind and will appear in your task list."
      }
    ],
    "isError": false
  },
  "id": 3
}

Tools Reference

create_personal_task

Creates a new task with category "personal" in the user's HeroMind account.

Parameters

  • name (string, required): Task description or title (1-500 characters)
  • start_date (string, optional): ISO 8601 earliest-start date. Informational only; no view places a task by it.
  • due_date (string, optional): ISO 8601. This is the day the task appears on in the planner and the Week View (date part used; defaults to today). Incomplete tasks roll forward from it. Set it to when the action is actually needed, never a shared batch date for several tasks.

Examples

Basic task:

{
  "name": "create_personal_task",
  "arguments": {
    "name": "Call dentist for appointment"
  }
}

Task with due date:

{
  "name": "create_personal_task",
  "arguments": {
    "name": "Submit tax documents",
    "due_date": "2024-04-15T23:59:59Z"
  }
}

Task with start and due dates:

{
  "name": "create_personal_task",
  "arguments": {
    "name": "Plan vacation itinerary",
    "start_date": "2024-02-01T09:00:00Z",
    "due_date": "2024-02-05T17:00:00Z"
  }
}

create_work_task

Creates a new task with category "work" in the user's HeroMind account.

Parameters

  • name (string, required): Task description or title (1-500 characters)
  • start_date (string, optional): ISO 8601 formatted datetime for when the task should start
  • due_date (string, optional): ISO 8601 formatted datetime for when the task is due

Examples

Project task:

{
  "name": "create_work_task",
  "arguments": {
    "name": "Review quarterly performance reports",
    "due_date": "2024-01-31T17:00:00Z"
  }
}

Meeting preparation:

{
  "name": "create_work_task",
  "arguments": {
    "name": "Prepare slides for client presentation",
    "start_date": "2024-01-20T09:00:00Z",
    "due_date": "2024-01-25T12:00:00Z"
  }
}

list_projects

Lists the user's HeroMind projects with the signals a coding session needs to pick the right one. Results are name-ordered and capped at 100 projects. The result text contains a JSON array of {id, name, current_focus, open_task_count, last_activity} where last_activity is the most recent of the project's updated_at, its latest task activity, and its latest log entry.

Parameters

  • include_archived (boolean, optional): Include archived projects (default false). When true, each entry also carries an archived flag.

Example

{
  "name": "list_projects",
  "arguments": {}
}

Response content (text):

Projects (2):
[
  {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "name": "HeroMind Library",
    "current_focus": "Ship the resurfacing loop",
    "open_task_count": 4,
    "last_activity": "2026-07-17T21:14:03.512Z"
  },
  ...
]

get_project_context

Loads a project's memory for session kickoff: current focus, the cached resume brief (or null if none / recently invalidated), the last 10 log entries, and up to 25 open tasks. Call this at the start of a coding session. The result text contains a JSON object:

{
  "project": { "id": "...", "name": "...", "current_focus": "..." },
  "resume_brief": { ... } ,
  "recent_log": [ { "kind": "session_summary", "source": "mcp", "content": "...", "created_at": "..." } ],
  "open_tasks": [ { "id": "...", "text": "...", "due_date": "...", "effort_minutes": 30, "work_notes": "..." } ]
}

Parameters

  • project_id (string, optional): Project UUID. Preferred; wins if both are given.
  • project_name (string, optional): Project name, matched case-insensitively. If the name matches more than one project, the call fails with a list of candidates (pass project_id instead).

One of project_id or project_name is required.

Example

{
  "name": "get_project_context",
  "arguments": {
    "project_name": "HeroMind Library"
  }
}

log_session_summary

Writes a coding session's outcome into the project's memory as a project_log_entries row with kind: "session_summary" and source: "mcp". Optionally completes and creates project tasks in the same call. Also nulls out the project's cached resume_brief (it is now stale and regenerates on next view). Call this at the end of a coding session.

Parameters

  • project_id / project_name: Same resolution rules as get_project_context (one required; project_id wins).
  • summary (string, required, max 2000 chars): What changed this session and what was decided. Stored as the log entry content; when next_steps is given it is appended as "\n\nNext steps: ...".
  • next_steps (string, optional, max 1000 chars): Suggested next steps for the following session.
  • completed_task_ids (string[], optional, max 50, UUIDs): Tasks to mark completed with today's completion date. Only tasks that belong to this user and this project are touched; already-completed tasks are skipped (their completion date stands). Skipped IDs are reported as a warning.
  • new_tasks (object[], optional, max 10): Follow-up tasks created in the project, due today. Category follows the project's folder (Work folder → work, otherwise personal). Each item:
    • text (string, required, max 500 chars)
    • effort_minutes (number, optional, 1-1440)
    • work_notes (string, optional, max 2000 chars)

Example

{
  "name": "log_session_summary",
  "arguments": {
    "project_name": "HeroMind Library",
    "summary": "Implemented the resurfacing cron and fixed the stale-topic query. Decided to cap resurfaced items at 3/day.",
    "next_steps": "Wire the resurfaced items into the daily planner card.",
    "completed_task_ids": ["123e4567-e89b-12d3-a456-426614174000"],
    "new_tasks": [
      { "text": "Add resurfaced-items card to daily planner", "effort_minutes": 45 }
    ]
  }
}

Response content (text):

✅ Logged session summary to project "HeroMind Library"
📝 Log entry ID: 9f0c...
✔️ Tasks completed: 1 (of 1 requested)
➕ Tasks created: 1 (a1b2...)
🔄 Resume brief invalidated: yes

list_tasks

Reconcile an external system with HeroMind. Newest-updated first.

ArgumentTypeNotes
statusopen \completed \alldefault open
categorypersonal \work \alldefault all
external_refstringexact match
updated_sinceISO 8601incremental sync; app-side completions bump updated_at (trigger added 2026-09-24)
limitnumberdefault 50, max 200

Returns JSON { count, tasks: [{ id, text, description, source_url, category, completed, completion_date, start_date, due_date, focused_date, starred, external_ref, created_at, updated_at }] }.

complete_task

{ task_id } or { external_ref }, optional completed: false to reopen. Writes what the app writes (completed + completion_date). Unknown ref → isError result, not a JSON-RPC error.

Task creation fields (both create tools)

ArgumentNotes
namerequired, ≤500
external_refyour stable key; a repeat create dedupes to the existing task (already_existed)
description≤2000, plain text with newlines — provenance ("From: … (account)" + link); shown under the task, URLs clickable, never rendered as HTML
source_url≤2000, http(s) — the run/thread that filed it; shown as a "Run" link
start_date, due_dateISO 8601

On an external_ref match the stored row is left alone except that a null description / source_url is filled in. Unknown fields are ignored.

upsert_daily_note

A note for a day on the owner's Daily Planner ("From your Chief of Staff"). Idempotent on external_ref: a second call replaces the note.

{ "external_ref": "desk:2026-09-24:morning-briefing", "date": "2026-09-24",
  "title": "3 things need you", "body": "## Changed\n…\n## Top 3\n…", "source_url": "https://agents.heromind.ai/threads/…" }

First line of the text content: {"id","result":"created"|"updated","external_ref","date"}. Limits: title ≤300, body ≤20000 (markdown, rendered, never raw HTML).

add_decision

Append to the owner's decision log (a decision context object visible through get_context). Same external_ref updates in place.

{ "external_ref": "decision:<loop-key>", "title": "I decided …", "detail": "why / rejected", "decided_at": "2026-09-24T09:15:00Z", "source_url": "…" }

Returns {"id","result":"created"|"updated","external_ref"} on the first line.

get_timeline

What happened, newest first: the owner's compiled timeline (task completions, journal, evidence, meetings, agent daily notes, decisions, explicit episodes). { since?, until?, person_slug?, limit? } — default the last 14 days, 60 rows, cap 300. Returns { count, person, episodes: [{ id, kind, at, summary, detail, people, project_id, quest_id, source, source_url }] }.

add_episode

Log something no other record holds. { external_ref, occurred_at, summary, kind?, detail?, people?: [names], project_id?, quest_id?, source_url? }. Idempotent on external_ref; people are matched to existing pages by name and unknown names are returned in people_unknown, never auto-created. Do not log task completions, journal entries or decisions here — those already feed the timeline.

get_context

Two modes.

Pack mode (recommended at the start of any task): { "query": "drafting the reply to Kurt about the Ramp intro", "budget": 4000 } → { pack, items, budget, budget_used, truncated, notes }. pack is markdown to paste ahead of your work: who you are working with (compiled Self page lead), standing preferences, decisions and stances ranked for the query (embedding similarity ∪ keyword overlap, recency), passages from the owner's journal/evidence/blueprint, and what is on their plate today. Budget 500–16000 characters.

Layer mode (no query): { "scope": "self|attention|week|strategy|all", "subject": {…}, "today": "YYYY-MM-DD" } → the layered JSON.

capture_context

Record the owner's judgment: up to 20 typed objects (decision, belief, mental_model, learning, open_question, preference, original, correction), one sentence each, first person. propose: true files them as proposed for the owner to accept on their Desk — use it for unattended capture (nightly sweeps, batch extraction). Near-duplicates (same kind + subject) return the existing id.

Library, people and book tools

library_add_source

Capture a source (web URL, YouTube video, pasted text/transcript, note) into the HeroMind Library. Without topic_slug it lands in the Library Inbox and the AI librarian classifies it; with topic_slug it files directly. For YouTube videos, fetching the transcript locally and passing it as text (with kind "youtube" and the url) is far more reliable than server-side transcript fetching.

ArgumentDescription
urlSource URL (web article or YouTube). Optional if text is provided.
textRaw text: a note, article body, or video transcript. PLAIN TEXT or MARKDOWN ONLY — never HTML, rendered email bodies, or anything containing CSS/markup (this text is read by humans and distilled into wikis verbatim). If your content exists as an HTML page or email, pass the underlying prose/markdown instead. Optional if url is provided.
titleTitle for the source (optional; extracted from the URL when possible).
kindOne of: web, youtube, pdf, note, thread, meeting. Inferred from the URL when omitted. "meeting" = notes or a transcript in text, with attendees and date.
topic_slugSlug of an existing Library topic to file into directly (see library_list_topics). Omit to let the librarian classify.
datekind "meeting" only: meeting date, YYYY-MM-DD.
visibilityprivate / agents / shared. Meetings default to private (agents cannot read them back until the owner changes it); everything else defaults to agents.

library_list_topics

List the user's HeroMind Library topics (name, slug, space, source counts) so sources can be filed deliberately.

library_get_updates

The Library change feed for agents. Sources are immutable, so change = additions: returns each topic whose wiki is behind (filed sources newer than the topic's last compile, or never compiled), articles explicitly marked stale, and the Inbox backlog. Call this at the START of a PKM session to decide which wikis to update.

ArgumentDescription
sinceOptional ISO 8601 timestamp (e.g. end of your last session) to also report how many sources were added since then.

Full-text search across the whole Library: wiki/editorial articles (title, dek, body) and sources (title, AI summary, raw text). Returns ranked matches with snippets. Supports websearch syntax ("exact phrase", -exclude, OR).

ArgumentDescription
query (required)Search query (websearch syntax).
limitMax results, 1-30 (default 12).
scopeOne of: all (default), articles, sources.

library_read_article

Read a Library article (wiki or editorial) in full: markdown body plus its provenance (the sources it cites). Identify it by topic_slug + article_slug (from library_get_topic_context or library_search) or by article_id.

ArgumentDescription
topic_slugTopic slug (pair with article_slug).
article_slugArticle slug within the topic.
article_idArticle UUID (alternative to the slug pair).

library_read_source

Read a Library source's full raw text (article body, video transcript, note) plus its AI summary and metadata. Use the source UUIDs returned by library_get_updates, library_get_topic_context, or library_read_article provenance. This is the material to read before updating a wiki.

ArgumentDescription
source_id (required)Source UUID.
max_charsMax raw-text characters to return, 500-200000 (default 50000).

library_get_topic_context

Load everything an agent needs to work on one Library topic: outline, all articles (with staleness), recent filed sources (★ marks ones newer than the last compile), and the user's open standing instructions (topic todos). Call before writing or updating a wiki/editorial.

ArgumentDescription
topic_slug (required)Topic slug (see library_list_topics).
include_source_summariesInclude each source\'s AI summary (default false; adds a lot of text).

library_write_article

Create or update a Library article (wiki or editorial) with markdown content. Upserts by slug within the topic: existing slug = update (article becomes current again), new slug = create (editorials get the next number). Pass source_ids to record provenance, and mark_topic_distilled=true when a wiki update covers all new sources so library_get_updates clears.

ArgumentDescription
topic_slug (required)Topic slug to write into (required).
kind (required)wiki (living reference doc) or editorial (numbered opinion piece).
title (required)Article title (required, max 300 chars).
content_md (required)Full markdown body (required).
slugKebab-case slug; omit to derive from title. Reuse an existing slug to update that article.
dekOne-line subtitle shown under the title (optional).
change_noteOne line on what changed and why (shown in the Library UI).
outline_groupWhich outline group of the topic this wiki article belongs to (optional).
source_idsUUIDs of Library sources this article draws on (provenance/citations).
mark_topic_distilledSet true when this write incorporates the topic\'s new sources; stamps the topic as freshly compiled.

library_get_person

What the owner knows about a person: the compiled Home (who they are, what they say and have done, where the owner's record diverges, open threads), recent timeline, linked sources, and the owner's non-private context about them. Call with no arguments to list all people pages. Use before a meeting or when a person is named in a task.

ArgumentDescription
namePerson name (or alias); fuzzy, case-insensitive.
slugExact person slug from the list.

library_create_person

Create a person page (e.g. "build me a person for X"). Then file 3–6 authoritative sources about them with library_add_source; the librarian links mentions and compiles the Home with footnotes. Never write prose about a person yourself. Returns the existing page if one already matches.

ArgumentDescription
name (required)Full name.
rolee.g. "CEO", "author", "CPO" (optional).
orgCompany / affiliation (optional).
relationshipcolleague / friend / family / public figure / … (optional).
aboutOne line on why this person matters to the owner (optional).

library_get_book

A book in the owner's Library: its compiled Home and the mirror (what the book, read against the owner's own record, is telling them; the sections that hit hardest with their cited records). No arguments = list all books.

ArgumentDescription
slugBook slug from the list.
titleBook title (fuzzy).

library_mirror_book

Ask the librarian to mirror a book: read each section against the owner's record (stances, Foundation, values, beliefs, quests, journal, evidence, prior mirrors) with a cross-model fact check. Needs the book's extracted text (the owner opens the book page once). Returns immediately; takes several minutes.

ArgumentDescription
slugBook slug (see library_get_book).
source_idOr the PDF source id.
depth"full" (per chapter, default) or "quick" (≤ 6 big sections).

library_get_changes

The Library's change feed since a moment: timeline events across topics (sources filed, Homes revised, articles created/revised/retired, notes, context captured), newest first, with a per-topic count. Use it to answer "what changed this week" or to decide which topics to look at, instead of scanning every topic.

ArgumentDescription
since (required)ISO date or datetime, e.g. 2026-09-01 or 2026-09-01T00:00:00Z.
topic_slugOptional: only this topic.
limit1..200, default 100.

Context tools (beyond get_context / capture_context)

supersede_context

Replace a current context object with a new statement when the user changes their mind or a decision is revised. The old object is kept as history (status superseded) and linked to the new one. Say so to the user once; never silently overwrite.

ArgumentDescription
id (required)UUID of the object being replaced (from get_context).

correct_context

The owner corrected something you (or a HeroMind page) stated as fact. Record a guard fact in THEIR words, linked to the subject, and recompile their Self page so the error does not survive. Then acknowledge in one line and never repeat the wrong claim. Use whenever the owner says "that's not right", "I never…", "we haven't…", "actually…".

ArgumentDescription
wrong_statement (required)The sentence that was wrong, as stated.
correct_fact (required)What is actually true, in the owner\'s words. One sentence.
subjectOptional: which page/subject the error concerned.
source_refOptional thread/session id where the correction happened.

trace_lineage

How has the owner's thinking about one idea changed over time? Gathers their decisions, stances (including superseded ones), journal entries and saved sources about the idea and returns: current live version, first mention, best articulation, turning points, reversals, abandoned branches, evidence gaps — every line dated and cited. Read-only. Use for "how has my thinking on X changed", "when did I first…", "did I reverse on…".

ArgumentDescription
idea (required)The idea, phrase, topic or claim to trace.
limitMax semantic hits to gather (5–60, default 30).

Error Codes

The server follows JSON-RPC 2.0 error code conventions with MCP-specific extensions:

JSON-RPC Standard Errors

  • -32700: Parse error - Invalid JSON
  • -32600: Invalid Request - Request structure is invalid
  • -32601: Method not found - The specified method does not exist
  • -32602: Invalid params - Invalid method parameters
  • -32603: Internal error - Server-side error

MCP-Specific Errors

  • -32000: Authentication failed - Invalid or missing authentication
  • -32001: Authorization failed - Insufficient permissions
  • -32002: Rate limit exceeded - Too many requests
  • -32003: Token expired - Authentication token has expired
  • -32004: Token inactive - Token has been deactivated
  • -32005: Tool not found - Specified tool does not exist
  • -32006: Tool execution failed - Tool execution encountered an error
  • -32007: Invalid token - Token format or content is invalid
  • -32008: Permission denied - Token lacks required permissions

Error Response Examples

Authentication Failed

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32000,
    "message": "Authorization header is required"
  },
  "id": "unknown"
}

Rate Limit Exceeded

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32002,
    "message": "Rate limit exceeded. Try again in 45 seconds",
    "data": {
      "current": 65,
      "limit": 60,
      "resetTime": 1704900000000
    }
  },
  "id": 5
}

Invalid Parameters

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32602,
    "message": "Invalid tool arguments: name is required and must be a non-empty string",
    "data": {
      "errors": ["name is required and must be a non-empty string"]
    }
  },
  "id": 6
}

Rate Limiting

Default Limits

  • 60 requests per minute per token (configurable)
  • Window: 60-second sliding window
  • Algorithm: Token bucket

Headers

Rate limit information is not included in response headers but can be monitored through the admin panel.

Handling Rate Limits

When rate limited (HTTP 429), the response includes:

  • Current request count
  • Rate limit threshold
  • Reset time (Unix timestamp)

Example retry logic:

if (response.status === 429) {
  const errorData = await response.json();
  const retryAfter = errorData.error.data.resetTime - Date.now();
  setTimeout(() => {
    // Retry request
  }, retryAfter);
}

Security Features

Request Validation

  • Size Limits: Maximum 10KB request body
  • Header Validation: Required Content-Type and Authorization headers
  • Input Sanitization: All input is sanitized and validated
  • Schema Validation: Tool arguments validated against JSON schema

Security Headers

All responses include security headers:

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
Strict-Transport-Security: max-age=31536000; includeSubDomains

Token Security

  • Hashing: SHA-256 hashed storage
  • Validation: Constant-time comparison
  • Expiration: Configurable token lifetimes
  • Revocation: Instant token deactivation
  • IP Restrictions: Optional IP whitelisting

Testing

Curl Examples

Initialize:

curl -X POST https://your-project.supabase.co/functions/v1/mcp-server \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05"},"id":1}'

List Tools:

curl -X POST https://your-project.supabase.co/functions/v1/mcp-server \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":2}'

Create Task:

curl -X POST https://your-project.supabase.co/functions/v1/mcp-server \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"create_personal_task","arguments":{"name":"Test task"}},"id":3}'

JavaScript/TypeScript Examples

interface MCPRequest {
  jsonrpc: "2.0";
  method: string;
  params?: any;
  id: string | number;
}

async function callMCPServer(request: MCPRequest, token?: string) {
  const headers: HeadersInit = {
    'Content-Type': 'application/json',
  };

  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }

  const response = await fetch('https://your-project.supabase.co/functions/v1/mcp-server', {
    method: 'POST',
    headers,
    body: JSON.stringify(request),
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  return response.json();
}

// Initialize connection
const initResponse = await callMCPServer({
  jsonrpc: "2.0",
  method: "initialize",
  params: { protocolVersion: "2024-11-05" },
  id: 1
});

// Create a task
const taskResponse = await callMCPServer({
  jsonrpc: "2.0",
  method: "tools/call",
  params: {
    name: "create_work_task",
    arguments: {
      name: "Review API documentation",
      due_date: "2024-01-20T17:00:00Z"
    }
  },
  id: 2
}, "your-token-here");

Monitoring & Analytics

Usage Tracking

The server automatically logs:

  • Request/response details
  • Performance metrics (response time)
  • Error rates and types
  • Client information (IP, User-Agent)
  • Tool usage patterns

Admin Dashboard

Monitor your MCP integration through the HeroMind admin panel:

  • Real-time usage statistics
  • Performance metrics
  • Error rate monitoring
  • Security event logging
  • Token management and analytics

Environment Variables

For production deployment, configure these environment variables:

# Required
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

# Optional (with defaults)
MCP_MAX_RATE_LIMIT=60
MCP_DEFAULT_TOKEN_EXPIRY_DAYS=90
MCP_ENABLE_USAGE_LOGS=true
MCP_DEBUG=false

Changelog

Version 1.3.0 (September 2026)

  • Two-way task sync: list_tasks, complete_task, external_ref dedupe
  • Task provenance: description and source_url on both create tools
  • Desk board: upsert_daily_note, add_decision (idempotent on external_ref)
  • get_context pack mode (query, budget) with a Recently section; capture_context { propose }
  • Timeline: get_timeline, add_episode
  • Library tools (library_*), context tools (get_context, capture_context, supersede_context, correct_context, trace_lineage), people and books
  • tasks.updated_at now maintained by trigger, so updated_since sees app-side completions

Version 1.2.0

  • Project-memory tools for the Claude Code session bridge: list_projects, get_project_context, log_session_summary
  • log_session_summary can complete and create project tasks in one call and invalidates the project's cached resume brief

Version 1.1.0

  • Library capture tools: library_add_source, library_list_topics

Version 1.0.0

  • Initial MCP implementation
  • Personal and work task creation tools
  • Token-based authentication
  • Rate limiting and security features
  • Comprehensive error handling
  • Usage analytics and monitoring

Future Versions

  • Additional task management tools (read, update, delete)
  • Project and habit integration
  • Bulk operations support
  • Advanced filtering and search capabilities

Support

For technical support and bug reports:

  1. Check the Integration Guide for common solutions
  2. Review token status and usage analytics in the admin panel
  3. Test individual endpoints using the provided curl examples
  4. Contact support with specific error messages and request/response examples

Updated 2026-09-27 · All chapters · API reference