2025-08-09 18:27:21 -07:00
#!/usr/bin/env node
/ * *
* Brain Cloud MCP Server
* Connects Claude to Brain Cloud for persistent AI memory
* /
import { Server } from '@modelcontextprotocol/sdk/server/index.js' ;
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' ;
import {
CallToolRequestSchema ,
ListToolsRequestSchema ,
Tool ,
} from '@modelcontextprotocol/sdk/types.js' ;
2025-08-10 11:32:59 -07:00
// Use native fetch (available in Node.js 18+)
2025-08-09 18:27:21 -07:00
// Configuration from environment
const CUSTOMER _ID = process . env . CUSTOMER _ID || 'demo-test-auto' ;
const BRAIN _CLOUD _URL = process . env . BRAIN _CLOUD _URL || 'https://brain-cloud.dpsifr.workers.dev' ;
class BrainCloudMCPServer {
constructor ( ) {
this . server = new Server (
{
name : 'brain-cloud' ,
version : '1.0.0' ,
} ,
{
capabilities : {
tools : { } ,
} ,
}
) ;
this . setupToolHandlers ( ) ;
this . setupErrorHandling ( ) ;
}
setupErrorHandling ( ) {
this . server . onerror = ( error ) => {
console . error ( '[MCP Error]' , error ) ;
} ;
process . on ( 'SIGINT' , async ( ) => {
await this . server . close ( ) ;
process . exit ( 0 ) ;
} ) ;
}
setupToolHandlers ( ) {
// List available tools
this . server . setRequestHandler ( ListToolsRequestSchema , async ( ) => {
return {
tools : [
{
name : 'remember' ,
description : 'Store a memory in Brain Cloud for persistent recall across sessions' ,
inputSchema : {
type : 'object' ,
properties : {
content : {
type : 'string' ,
description : 'The information to remember'
} ,
context : {
type : 'string' ,
description : 'Additional context or tags for the memory'
}
} ,
required : [ 'content' ]
}
} ,
{
name : 'recall' ,
description : 'Search and retrieve memories from Brain Cloud' ,
inputSchema : {
type : 'object' ,
properties : {
query : {
type : 'string' ,
description : 'What to search for in memories'
} ,
limit : {
type : 'number' ,
description : 'Number of memories to retrieve (default: 10)'
}
} ,
required : [ 'query' ]
}
} ,
{
name : 'get_all_memories' ,
description : 'Get all stored memories from Brain Cloud' ,
inputSchema : {
type : 'object' ,
properties : {
limit : {
type : 'number' ,
description : 'Number of memories to retrieve (default: 50)'
}
}
}
} ,
{
name : 'brain_cloud_status' ,
description : 'Check Brain Cloud connection and memory statistics' ,
inputSchema : {
type : 'object' ,
properties : { }
}
}
]
} ;
} ) ;
// Handle tool calls
this . server . setRequestHandler ( CallToolRequestSchema , async ( request ) => {
const { name , arguments : args } = request . params ;
try {
switch ( name ) {
case 'remember' :
return await this . storeMemory ( args . content , args . context ) ;
case 'recall' :
return await this . searchMemories ( args . query , args . limit || 10 ) ;
case 'get_all_memories' :
return await this . getAllMemories ( args . limit || 50 ) ;
case 'brain_cloud_status' :
return await this . getStatus ( ) ;
default :
throw new Error ( ` Unknown tool: ${ name } ` ) ;
}
} catch ( error ) {
return {
content : [ {
type : 'text' ,
text : ` Error: ${ error . message } `
} ] ,
isError : true
} ;
}
} ) ;
}
async storeMemory ( content , context = '' ) {
try {
const response = await fetch ( ` ${ BRAIN _CLOUD _URL } /memory ` , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
'x-customer-id' : CUSTOMER _ID
} ,
body : JSON . stringify ( {
content ,
context ,
source : 'claude-mcp' ,
timestamp : new Date ( ) . toISOString ( )
} )
} ) ;
if ( ! response . ok ) {
throw new Error ( ` Brain Cloud API error: ${ response . status } ` ) ;
}
const result = await response . json ( ) ;
return {
content : [ {
type : 'text' ,
text : ` ✅ Memory stored successfully! \n \n Content: ${ content } \n ID: ${ result . id || 'generated' } \n \n I'll remember this for future conversations. `
} ]
} ;
} catch ( error ) {
throw new Error ( ` Failed to store memory: ${ error . message } ` ) ;
}
}
async searchMemories ( query , limit = 10 ) {
try {
const response = await fetch ( ` ${ BRAIN _CLOUD _URL } /search ` , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
'x-customer-id' : CUSTOMER _ID
} ,
body : JSON . stringify ( {
query ,
limit
} )
} ) ;
if ( ! response . ok ) {
throw new Error ( ` Brain Cloud API error: ${ response . status } ` ) ;
}
const result = await response . json ( ) ;
const memories = result . memories || [ ] ;
if ( memories . length === 0 ) {
return {
content : [ {
type : 'text' ,
text : ` 🔍 No memories found for " ${ query } " \n \n Try a different search term or ask me to remember something first. `
} ]
} ;
}
const memoryList = memories . map ( ( memory , index ) => {
const date = new Date ( memory . created || memory . timestamp ) . toLocaleDateString ( ) ;
return ` ${ index + 1 } . ${ memory . content } ( ${ date } ) ` ;
} ) . join ( '\n' ) ;
return {
content : [ {
type : 'text' ,
text : ` 🧠 Found ${ memories . length } memories for " ${ query } ": \n \n ${ memoryList } \n \n I can use this context to help with your current request! `
} ]
} ;
} catch ( error ) {
throw new Error ( ` Failed to search memories: ${ error . message } ` ) ;
}
}
async getAllMemories ( limit = 50 ) {
try {
const response = await fetch ( ` ${ BRAIN _CLOUD _URL } /memories ` , {
method : 'GET' ,
headers : {
'x-customer-id' : CUSTOMER _ID
}
} ) ;
if ( ! response . ok ) {
throw new Error ( ` Brain Cloud API error: ${ response . status } ` ) ;
}
const result = await response . json ( ) ;
const memories = result . memories || [ ] ;
if ( memories . length === 0 ) {
return {
content : [ {
type : 'text' ,
text : ` 🧠 No memories stored yet. \n \n Start a conversation and I'll automatically remember important details! `
} ]
} ;
}
const recentMemories = memories . slice ( 0 , limit ) ;
const memoryList = recentMemories . map ( ( memory , index ) => {
const date = new Date ( memory . created || memory . timestamp ) . toLocaleDateString ( ) ;
return ` ${ index + 1 } . ${ memory . content } ( ${ date } ) ` ;
} ) . join ( '\n' ) ;
return {
content : [ {
type : 'text' ,
text : ` 🧠 Your Brain Cloud contains ${ memories . length } total memories. \n \n Showing most recent ${ recentMemories . length } : \n \n ${ memoryList } `
} ]
} ;
} catch ( error ) {
throw new Error ( ` Failed to get memories: ${ error . message } ` ) ;
}
}
async getStatus ( ) {
try {
const response = await fetch ( ` ${ BRAIN _CLOUD _URL } /health ` , {
method : 'GET' ,
headers : {
'x-customer-id' : CUSTOMER _ID
}
} ) ;
if ( ! response . ok ) {
throw new Error ( ` Brain Cloud API error: ${ response . status } ` ) ;
}
const result = await response . json ( ) ;
// Get memory count
const memoriesResponse = await fetch ( ` ${ BRAIN _CLOUD _URL } /memories ` , {
headers : { 'x-customer-id' : CUSTOMER _ID }
} ) ;
let memoryCount = 0 ;
if ( memoriesResponse . ok ) {
const memoriesData = await memoriesResponse . json ( ) ;
memoryCount = memoriesData . memories ? . length || 0 ;
}
return {
content : [ {
type : 'text' ,
text : ` 🧠 Brain Cloud Status: ${ result . status } \n \n ` +
` Customer ID: ${ CUSTOMER _ID } \n ` +
` Total Memories: ${ memoryCount } \n ` +
` Last Check: ${ new Date ( ) . toLocaleString ( ) } \n \n ` +
` ✅ I'm connected and ready to remember everything! `
} ]
} ;
} catch ( error ) {
throw new Error ( ` Failed to get Brain Cloud status: ${ error . message } ` ) ;
}
}
async run ( ) {
const transport = new StdioServerTransport ( ) ;
await this . server . connect ( transport ) ;
console . error ( ` 🧠 Brain Cloud MCP Server running for customer: ${ CUSTOMER _ID } ` ) ;
}
}
// Start the server
const server = new BrainCloudMCPServer ( ) ;
server . run ( ) . catch ( console . error ) ;