Second Brain Copilot Documentation
Second Brain Copilot exposes your Notion HuB databases through two interfaces: the Model Context Protocol (MCP) for AI agents and a REST API for custom applications.
Both interfaces use the same OAuth2 authentication, permissions model, and people-based access filtering.
Authentication
All access requires a session token obtained via Notion OAuth:
- Visit
/auth/notionin your browser - Authorize the integration in Notion
- Copy your session token from the callback page
- Use it as a Bearer token:
Authorization: Bearer <token>
Tokens are single-use: once an MCP client connects with a token, it activates into a session. For the web dashboard, tokens are stored in localStorage and validated via /auth/status.
Claude Desktop Configuration
Add this to your Claude Desktop MCP config file (claude_desktop_config.json):
{
"mcpServers": {
"second-brain": {
"url": "http://localhost:3100/mcp",
"headers": {
"Authorization": "Bearer YOUR_SESSION_TOKEN"
}
}
}
}
After adding the config, restart Claude Desktop. The Second Brain tools will appear in the tools menu.
Cursor Configuration
In Cursor settings, navigate to MCP Servers and add:
{
"second-brain": {
"url": "http://localhost:3100/mcp",
"headers": {
"Authorization": "Bearer YOUR_SESSION_TOKEN"
}
}
}
Claude Code Configuration
In your project's .mcp.json or Claude Code settings, add:
{
"mcpServers": {
"second-brain": {
"type": "url",
"url": "http://localhost:3100/mcp",
"headers": {
"Authorization": "Bearer YOUR_SESSION_TOKEN"
}
}
}
}
Custom MCP Clients
Use the @modelcontextprotocol/sdk package to build custom clients:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from
"@modelcontextprotocol/sdk/client/streamableHttp.js";
const transport = new StreamableHTTPClientTransport(
new URL("http://localhost:3100/mcp"),
{
requestInit: {
headers: {
Authorization: "Bearer YOUR_SESSION_TOKEN",
},
},
}
);
const client = new Client({ name: "my-app", version: "1.0" });
await client.connect(transport);
// List available tools
const tools = await client.listTools();
console.log(tools);
// Call a tool
const result = await client.callTool({
name: "query_hub",
arguments: { hub: "action", limit: 5 },
});
console.log(result);
Available MCP Tools
The following tools are available through the MCP protocol:
| Tool | Description | Parameters |
|---|---|---|
list_hubs | List all available HuB databases | None |
get_hub_schema | Get property schema for a HuB | hub (string) |
query_hub | Query pages from a HuB with filters | hub, filter?, sort?, limit? |
create_page | Create a new page in a HuB | hub, properties (object) |
update_page | Update an existing page | pageId, hub, properties |
get_page | Get a single page by ID | pageId |
comment_on_page | Add a comment to a page | pageId, text |
search_people | Search the people directory | query |
REST API — Authentication
All API requests require a Bearer token in the Authorization header:
Authorization: Bearer YOUR_SESSION_TOKEN
Obtain a token by completing the OAuth flow at /auth/notion.
You can validate your token with:
Returns { "authenticated": true, "user": { "name", "email", "role" } } or { "authenticated": false }.
Base URL & Error Format
Base URL: http://localhost:3100/api
All error responses follow this format:
{
"error": "Human-readable error message"
}
HTTP status codes: 400 bad request, 401 unauthorized, 403 forbidden, 404 not found, 500 server error.
List HuBs
Returns all configured HuB databases.
Response:
{
"hubs": [
{ "key": "action", "label": "Action", "description": "Tasks, actions...", "propertyCount": 28 },
{ "key": "outcome", "label": "Outcome", ... }
]
}
Get HuB Schema
Returns the full schema for a HuB including all properties, their types, options, and your access level.
Response:
{
"hub": "action",
"label": "Action",
"databaseId": "22430fc8...",
"properties": [
{ "name": "Title", "type": "title" },
{ "name": "Status", "type": "status", "options": ["Backlog", "In Progress", "Done", "Cancelled"] },
{ "name": "Priority", "type": "select", "options": ["P0 – Critical", ...] }
],
"access": { "canWrite": true, "writableHubs": ["*"], "role": "admin" }
}
Query Pages
Query pages from a HuB with optional filtering, sorting, and pagination.
Query parameters:
filter— Filter expression (see Filter Syntax)sort— Sort expression (see Sort Syntax)limit— Max results (default 20, max 100)
Example:
GET /api/hubs/action/pages?filter=Status=In Progress&sort=Due:asc&limit=10
Response:
{
"hub": "action",
"count": 3,
"pages": [
{
"id": "abc123...",
"created_time": "2025-01-15T10:30:00Z",
"last_edited_time": "2025-01-16T08:00:00Z",
"properties": {
"Title": "Review Q4 report",
"Status": "In Progress",
"Priority": "P1 – Major",
"Due": { "start": "2025-01-20", "end": null }
}
}
]
}
Create Page
Create a new page in a HuB. Requires write permission.
Request body:
{
"properties": {
"Title": "Follow up with client",
"Status": "Backlog",
"Priority": "P2 – Moderate",
"Domain": "Sales",
"Due": "2025-02-01"
}
}
Response: 201 Created
{
"success": true,
"page": { "id": "new-page-id", ... }
}
Get Page
Retrieve a single page by its Notion page ID. Access is checked against people properties.
Response:
{
"id": "abc123...",
"created_time": "2025-01-15T10:30:00Z",
"last_edited_time": "2025-01-16T08:00:00Z",
"properties": { ... }
}
Update Page
Update properties on an existing page. Requires write permission for the HuB.
Request body:
{
"hub": "action",
"properties": {
"Status": "Done",
"Done Date": "2025-01-18"
}
}
Add Comment
Add a comment to a page.
Request body:
{
"text": "Updated the status and assigned to Pankaj."
}
Response: { "success": true, "commentId": "..." }
Search People
Search the workspace people directory by name or email.
Response:
{
"query": "pankaj",
"count": 1,
"people": [{ "id": "...", "name": "Pankaj", "type": "person", "email": "pankaj.shrestha@itsutra.com" }]
}
People Directory
Returns the full people directory (all workspace members and bots). Used by the web dashboard for client-side name resolution.
Response:
{
"count": 42,
"people": [
{ "id": "...", "name": "Pankaj", "type": "person", "email": "pankaj.shrestha@itsutra.com" },
{ "id": "...", "name": "Zapier", "type": "bot", "email": null }
]
}
Property Value Formats
When creating or updating pages, property values should be provided in simplified format:
| Type | Value Format | Example |
|---|---|---|
title | String | "Review Q4 report" |
rich_text | String | "Some notes here" |
select | Option name (string) | "P1 – Major" |
multi_select | Array of option names | ["IT", "HR"] |
status | Status name (string) | "In Progress" |
date | ISO date string | "2025-01-20" |
number | Number | 42 |
checkbox | Boolean | true |
people | Array of user IDs | ["user-id-1"] |
relation | Array of page IDs | ["page-id-1"] |
url | URL string | "https://example.com" |
email | Email string | "user@example.com" |
phone_number | Phone string | "+1-555-0123" |
Filter Syntax
Filters use a simple Property=Value format passed as a query string parameter:
# Simple equality
filter=Status=In Progress
# Multiple filters (AND)
filter=Status=In Progress,Priority=P1 – Major
# The server translates these into Notion API filter objects
# based on the property type.
The server automatically determines the correct filter operator based on the property type (e.g., equals for select, contains for text).
Sort Syntax
Sorts use Property:direction format:
# Single sort
sort=Due:asc
# Multiple sorts (comma-separated)
sort=Priority:desc,Due:asc
Direction is either asc (ascending) or desc (descending).