#!/usr/bin/env python3
"""
Google Workspace MCP Server
Full integration with Gmail, Calendar, Sheets, Docs, and Drive
"""
import sys
import json
import asyncio
import traceback
from pathlib import Path
from datetime import datetime
sys.path.insert(0, str(Path(__file__).parent.parent))
from mcp.server import Server
from mcp.types import Tool, TextContent
import src.google_sheets as sheets
import src.google_gmail as gmail
import src.google_calendar as calendar
import src.google_docs as docs
import src.google_drive as drive
import src.local_storage as storage
import src.memory_system as memory
from src.logger import get_logger, log_tool_call, log_exception
# Initialize logger
logger = get_logger('mcp_server')
logger.info("=" * 60)
logger.info("MCP SERVER STARTING")
logger.info("=" * 60)
def load_config():
try:
config_path = Path(__file__).parent.parent / 'config.json'
with open(config_path, 'r') as f:
config_data = json.load(f)
logger.info(f"Config loaded from {config_path}")
return config_data
except FileNotFoundError:
logger.warning(f"Config file not found at {config_path}, using defaults")
return {'google': {}}
except json.JSONDecodeError as e:
logger.error(f"Invalid JSON in config file: {e}")
return {'google': {}}
except Exception as e:
logger.error(f"Error loading config: {e}")
return {'google': {}}
config = load_config()
server = Server("google-workspace-mcp-server")
@server.list_tools()
async def list_tools():
return [
# ==================== SHEETS TOOLS ====================
Tool(
name="create_spreadsheet",
description="Create a new Google Spreadsheet with optional multiple sheets/tabs",
inputSchema={
"type": "object",
"properties": {
"title": {"type": "string", "description": "Title of the spreadsheet"},
"sheetNames": {
"type": "array",
"items": {"type": "string"},
"description": "Optional list of sheet/tab names to create"
}
},
"required": ["title"]
}
),
Tool(
name="read_sheet",
description="Read data from a Google Sheet range",
inputSchema={
"type": "object",
"properties": {
"spreadsheetId": {"type": "string", "description": "The ID of the spreadsheet"},
"range": {"type": "string", "description": "The range to read (e.g., 'Sheet1!A1:B10')"}
},
"required": ["spreadsheetId", "range"]
}
),
Tool(
name="write_sheet",
description="Write data to a Google Sheet range",
inputSchema={
"type": "object",
"properties": {
"spreadsheetId": {"type": "string"},
"range": {"type": "string"},
"values": {
"type": "array",
"items": {"type": "array", "items": {"type": "string"}},
"description": "2D array of values to write"
}
},
"required": ["spreadsheetId", "range", "values"]
}
),
Tool(
name="append_sheet",
description="Append data to a Google Sheet",
inputSchema={
"type": "object",
"properties": {
"spreadsheetId": {"type": "string"},
"range": {"type": "string"},
"values": {
"type": "array",
"items": {"type": "array", "items": {"type": "string"}}
}
},
"required": ["spreadsheetId", "range", "values"]
}
),
Tool(
name="get_sheet_info",
description="Get information about a Google Sheet including all tabs",
inputSchema={
"type": "object",
"properties": {
"spreadsheetId": {"type": "string"}
},
"required": ["spreadsheetId"]
}
),
Tool(
name="create_sheet_tab",
description="Create a new tab/worksheet in an existing spreadsheet",
inputSchema={
"type": "object",
"properties": {
"spreadsheetId": {"type": "string"},
"tabName": {"type": "string", "description": "Name for the new tab"}
},
"required": ["spreadsheetId", "tabName"]
}
),
Tool(
name="list_spreadsheets",
description="List all spreadsheets in Google Drive",
inputSchema={
"type": "object",
"properties": {
"maxResults": {"type": "integer", "description": "Maximum number of results", "default": 50}
}
}
),
Tool(
name="format_cells",
description="Format cells in a spreadsheet (bold, colors, borders, alignment)",
inputSchema={
"type": "object",
"properties": {
"spreadsheetId": {"type": "string"},
"range": {"type": "string"},
"formatOptions": {
"type": "object",
"description": "Format options: bold, italic, fontSize, foregroundColor, backgroundColor, horizontalAlignment, borders",
"properties": {
"bold": {"type": "boolean"},
"italic": {"type": "boolean"},
"fontSize": {"type": "integer"},
"foregroundColor": {
"type": "object",
"properties": {
"red": {"type": "number"},
"green": {"type": "number"},
"blue": {"type": "number"}
}
},
"backgroundColor": {
"type": "object",
"properties": {
"red": {"type": "number"},
"green": {"type": "number"},
"blue": {"type": "number"}
}
},
"horizontalAlignment": {"type": "string", "enum": ["LEFT", "CENTER", "RIGHT"]},
"verticalAlignment": {"type": "string", "enum": ["TOP", "MIDDLE", "BOTTOM"]}
}
}
},
"required": ["spreadsheetId", "range", "formatOptions"]
}
),
Tool(
name="add_formula",
description="Add a formula to a specific cell",
inputSchema={
"type": "object",
"properties": {
"spreadsheetId": {"type": "string"},
"cell": {"type": "string", "description": "Cell reference (e.g., 'A1' or 'Sheet1!A1')"},
"formula": {"type": "string", "description": "Formula to add (e.g., '=SUM(A1:A10)')"}
},
"required": ["spreadsheetId", "cell", "formula"]
}
),
Tool(
name="share_spreadsheet",
description="Share a spreadsheet with a user",
inputSchema={
"type": "object",
"properties": {
"spreadsheetId": {"type": "string"},
"email": {"type": "string", "description": "Email address to share with"},
"role": {"type": "string", "enum": ["reader", "writer", "commenter"], "default": "reader"}
},
"required": ["spreadsheetId", "email"]
}
),
Tool(
name="create_job_tracker",
description="Create a job tracker spreadsheet with predefined columns for Applications, Interviews, and Offers",
inputSchema={
"type": "object",
"properties": {
"title": {"type": "string", "description": "Title for the job tracker", "default": "Job Applications Tracker"}
}
}
),
# ==================== GMAIL TOOLS ====================
Tool(
name="list_emails",
description="List emails from Gmail",
inputSchema={
"type": "object",
"properties": {
"maxResults": {"type": "integer", "description": "Maximum number of emails", "default": 10},
"query": {"type": "string", "description": "Gmail search query", "default": ""}
}
}
),
Tool(
name="get_email_detail",
description="Get detailed information about a specific email",
inputSchema={
"type": "object",
"properties": {
"messageId": {"type": "string", "description": "The Gmail message ID"}
},
"required": ["messageId"]
}
),
Tool(
name="send_email",
description="Send an email via Gmail",
inputSchema={
"type": "object",
"properties": {
"to": {"type": "string", "description": "Recipient email address"},
"subject": {"type": "string", "description": "Email subject"},
"body": {"type": "string", "description": "Email body content"},
"isHtml": {"type": "boolean", "description": "Whether the body is HTML", "default": False}
},
"required": ["to", "subject", "body"]
}
),
Tool(
name="search_emails",
description="Search emails in Gmail",
inputSchema={
"type": "object",
"properties": {
"query": {"type": "string", "description": "Gmail search query"}
},
"required": ["query"]
}
),
Tool(
name="create_draft",
description="Create a draft email",
inputSchema={
"type": "object",
"properties": {
"to": {"type": "string", "description": "Recipient email address"},
"subject": {"type": "string", "description": "Email subject"},
"body": {"type": "string", "description": "Email body content"},
"isHtml": {"type": "boolean", "default": False},
"cc": {"type": "string", "description": "CC recipients"},
"bcc": {"type": "string", "description": "BCC recipients"}
},
"required": ["to", "subject", "body"]
}
),
Tool(
name="list_drafts",
description="List all draft emails",
inputSchema={
"type": "object",
"properties": {
"maxResults": {"type": "integer", "default": 20}
}
}
),
Tool(
name="get_draft",
description="Get a specific draft by ID",
inputSchema={
"type": "object",
"properties": {
"draftId": {"type": "string"}
},
"required": ["draftId"]
}
),
Tool(
name="update_draft",
description="Update an existing draft",
inputSchema={
"type": "object",
"properties": {
"draftId": {"type": "string"},
"to": {"type": "string"},
"subject": {"type": "string"},
"body": {"type": "string"},
"isHtml": {"type": "boolean", "default": False}
},
"required": ["draftId"]
}
),
Tool(
name="send_draft",
description="Send an existing draft",
inputSchema={
"type": "object",
"properties": {
"draftId": {"type": "string"}
},
"required": ["draftId"]
}
),
Tool(
name="delete_draft",
description="Delete a draft",
inputSchema={
"type": "object",
"properties": {
"draftId": {"type": "string"}
},
"required": ["draftId"]
}
),
Tool(
name="reply_to_email",
description="Reply to an existing email thread",
inputSchema={
"type": "object",
"properties": {
"messageId": {"type": "string", "description": "Original message ID"},
"body": {"type": "string", "description": "Reply body"},
"isHtml": {"type": "boolean", "default": False}
},
"required": ["messageId", "body"]
}
),
Tool(
name="forward_email",
description="Forward an email to another recipient",
inputSchema={
"type": "object",
"properties": {
"messageId": {"type": "string"},
"to": {"type": "string", "description": "Recipient to forward to"},
"additionalMessage": {"type": "string", "description": "Additional message to include"}
},
"required": ["messageId", "to"]
}
),
Tool(
name="add_label",
description="Add a label to an email",
inputSchema={
"type": "object",
"properties": {
"messageId": {"type": "string"},
"labelName": {"type": "string"}
},
"required": ["messageId", "labelName"]
}
),
Tool(
name="list_labels",
description="List all Gmail labels",
inputSchema={
"type": "object",
"properties": {}
}
),
Tool(
name="trash_email",
description="Move an email to trash",
inputSchema={
"type": "object",
"properties": {
"messageId": {"type": "string"}
},
"required": ["messageId"]
}
),
Tool(
name="archive_email",
description="Archive an email",
inputSchema={
"type": "object",
"properties": {
"messageId": {"type": "string"}
},
"required": ["messageId"]
}
),
Tool(
name="create_followup_draft",
description="Create a follow-up email draft for job applications",
inputSchema={
"type": "object",
"properties": {
"companyName": {"type": "string"},
"contactName": {"type": "string"},
"position": {"type": "string"},
"daysSinceApplication": {"type": "integer", "default": 7}
},
"required": ["companyName", "contactName", "position"]
}
),
Tool(
name="create_thank_you_draft",
description="Create a thank you email draft after an interview",
inputSchema={
"type": "object",
"properties": {
"interviewerName": {"type": "string"},
"companyName": {"type": "string"},
"position": {"type": "string"},
"interviewTopics": {"type": "array", "items": {"type": "string"}}
},
"required": ["interviewerName", "companyName", "position"]
}
),
# ==================== CALENDAR TOOLS ====================
Tool(
name="list_calendar_events",
description="List upcoming calendar events",
inputSchema={
"type": "object",
"properties": {
"calendarId": {"type": "string", "description": "Calendar ID (default: primary)", "default": "primary"},
"maxResults": {"type": "integer", "description": "Maximum number of events", "default": 10},
"timeMin": {"type": "string", "description": "Minimum time (ISO 8601 format)"}
}
}
),
Tool(
name="create_calendar_event",
description="Create a new calendar event",
inputSchema={
"type": "object",
"properties": {
"calendarId": {"type": "string", "default": "primary"},
"summary": {"type": "string", "description": "Event title"},
"description": {"type": "string", "description": "Event description"},
"start": {"type": "string", "description": "Start time (ISO 8601 format)"},
"end": {"type": "string", "description": "End time (ISO 8601 format)"},
"location": {"type": "string", "description": "Event location"},
"attendees": {
"type": "array",
"items": {"type": "string"},
"description": "Array of attendee email addresses"
},
"timeZone": {"type": "string", "default": "America/Los_Angeles"}
},
"required": ["summary", "start", "end"]
}
),
Tool(
name="update_calendar_event",
description="Update an existing calendar event",
inputSchema={
"type": "object",
"properties": {
"calendarId": {"type": "string", "default": "primary"},
"eventId": {"type": "string", "description": "Event ID to update"},
"summary": {"type": "string"},
"description": {"type": "string"},
"start": {"type": "string"},
"end": {"type": "string"},
"location": {"type": "string"},
"attendees": {"type": "array", "items": {"type": "string"}}
},
"required": ["eventId"]
}
),
Tool(
name="delete_calendar_event",
description="Delete a calendar event",
inputSchema={
"type": "object",
"properties": {
"calendarId": {"type": "string", "default": "primary"},
"eventId": {"type": "string", "description": "Event ID to delete"}
},
"required": ["eventId"]
}
),
Tool(
name="get_calendar_event",
description="Get details of a specific calendar event",
inputSchema={
"type": "object",
"properties": {
"calendarId": {"type": "string", "default": "primary"},
"eventId": {"type": "string", "description": "Event ID"}
},
"required": ["eventId"]
}
),
# ==================== DOCS TOOLS ====================
Tool(
name="create_document",
description="Create a new Google Document with optional initial content",
inputSchema={
"type": "object",
"properties": {
"title": {"type": "string", "description": "Document title"},
"initialContent": {"type": "string", "description": "Optional initial text content"}
},
"required": ["title"]
}
),
Tool(
name="read_document",
description="Read the content of a Google Document",
inputSchema={
"type": "object",
"properties": {
"documentId": {"type": "string", "description": "The document ID"}
},
"required": ["documentId"]
}
),
Tool(
name="append_to_document",
description="Append text to the end of a Google Document",
inputSchema={
"type": "object",
"properties": {
"documentId": {"type": "string"},
"content": {"type": "string", "description": "Text content to append"}
},
"required": ["documentId", "content"]
}
),
Tool(
name="format_document_text",
description="Apply formatting to text in a document (bold, italic, fontSize, colors)",
inputSchema={
"type": "object",
"properties": {
"documentId": {"type": "string"},
"startIndex": {"type": "integer", "description": "Start index of text to format"},
"endIndex": {"type": "integer", "description": "End index of text to format"},
"formatOptions": {
"type": "object",
"properties": {
"bold": {"type": "boolean"},
"italic": {"type": "boolean"},
"underline": {"type": "boolean"},
"fontSize": {"type": "integer"},
"link": {"type": "string", "description": "URL to link to"}
}
}
},
"required": ["documentId", "startIndex", "endIndex", "formatOptions"]
}
),
Tool(
name="apply_paragraph_style",
description="Apply paragraph styling (headings, alignment)",
inputSchema={
"type": "object",
"properties": {
"documentId": {"type": "string"},
"startIndex": {"type": "integer"},
"endIndex": {"type": "integer"},
"styleOptions": {
"type": "object",
"properties": {
"namedStyleType": {
"type": "string",
"enum": ["HEADING_1", "HEADING_2", "HEADING_3", "TITLE", "SUBTITLE", "NORMAL_TEXT"]
},
"alignment": {"type": "string", "enum": ["START", "CENTER", "END", "JUSTIFIED"]}
}
}
},
"required": ["documentId", "startIndex", "endIndex", "styleOptions"]
}
),
Tool(
name="insert_table",
description="Insert a table into a Google Document",
inputSchema={
"type": "object",
"properties": {
"documentId": {"type": "string"},
"rows": {"type": "integer", "description": "Number of rows"},
"cols": {"type": "integer", "description": "Number of columns"},
"data": {
"type": "array",
"items": {"type": "array", "items": {"type": "string"}},
"description": "Optional 2D array of cell data"
},
"index": {"type": "integer", "description": "Position to insert (optional, defaults to end)"}
},
"required": ["documentId", "rows", "cols"]
}
),
Tool(
name="insert_bullet_list",
description="Insert a bullet list into a document",
inputSchema={
"type": "object",
"properties": {
"documentId": {"type": "string"},
"items": {
"type": "array",
"items": {"type": "string"},
"description": "List items"
},
"index": {"type": "integer", "description": "Position to insert (optional)"}
},
"required": ["documentId", "items"]
}
),
Tool(
name="insert_numbered_list",
description="Insert a numbered list into a document",
inputSchema={
"type": "object",
"properties": {
"documentId": {"type": "string"},
"items": {
"type": "array",
"items": {"type": "string"},
"description": "List items"
},
"index": {"type": "integer", "description": "Position to insert (optional)"}
},
"required": ["documentId", "items"]
}
),
Tool(
name="list_documents",
description="List all Google Docs in Drive",
inputSchema={
"type": "object",
"properties": {
"maxResults": {"type": "integer", "default": 50}
}
}
),
Tool(
name="share_document",
description="Share a document with a user",
inputSchema={
"type": "object",
"properties": {
"documentId": {"type": "string"},
"email": {"type": "string"},
"role": {"type": "string", "enum": ["reader", "writer", "commenter"], "default": "reader"}
},
"required": ["documentId", "email"]
}
),
Tool(
name="create_daily_report",
description="Create a daily report document with predefined sections",
inputSchema={
"type": "object",
"properties": {
"title": {"type": "string", "description": "Report title (optional, defaults to dated title)"},
"sections": {
"type": "object",
"properties": {
"summary": {"type": "string"},
"tasks_completed": {"type": "array", "items": {"type": "string"}},
"tasks_pending": {"type": "array", "items": {"type": "string"}},
"notes": {"type": "string"}
}
}
}
}
),
# ==================== DRIVE TOOLS ====================
Tool(
name="list_files",
description="List files in Google Drive",
inputSchema={
"type": "object",
"properties": {
"folderId": {"type": "string", "description": "Folder ID to list (optional, root if not specified)"},
"query": {"type": "string", "description": "Additional search query"},
"maxResults": {"type": "integer", "default": 50}
}
}
),
Tool(
name="list_folders",
description="List only folders in Google Drive",
inputSchema={
"type": "object",
"properties": {
"parentFolderId": {"type": "string", "description": "Parent folder ID (optional)"},
"maxResults": {"type": "integer", "default": 50}
}
}
),
Tool(
name="create_folder",
description="Create a new folder in Google Drive",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string", "description": "Folder name"},
"parentFolderId": {"type": "string", "description": "Parent folder ID (optional)"}
},
"required": ["name"]
}
),
Tool(
name="upload_file",
description="Upload a file to Google Drive",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string", "description": "File name"},
"content": {"type": "string", "description": "File content (text or base64 for binary)"},
"mimeType": {"type": "string", "description": "MIME type", "default": "text/plain"},
"folderId": {"type": "string", "description": "Destination folder ID (optional)"}
},
"required": ["name", "content"]
}
),
Tool(
name="download_file",
description="Download a file from Google Drive",
inputSchema={
"type": "object",
"properties": {
"fileId": {"type": "string", "description": "File ID to download"}
},
"required": ["fileId"]
}
),
Tool(
name="move_file",
description="Move a file to a different folder",
inputSchema={
"type": "object",
"properties": {
"fileId": {"type": "string"},
"newFolderId": {"type": "string", "description": "Destination folder ID"}
},
"required": ["fileId", "newFolderId"]
}
),
Tool(
name="copy_file",
description="Copy a file in Google Drive",
inputSchema={
"type": "object",
"properties": {
"fileId": {"type": "string"},
"newName": {"type": "string", "description": "Name for the copy (optional)"},
"folderId": {"type": "string", "description": "Destination folder (optional)"}
},
"required": ["fileId"]
}
),
Tool(
name="delete_file",
description="Delete a file or folder (moves to trash)",
inputSchema={
"type": "object",
"properties": {
"fileId": {"type": "string", "description": "File or folder ID to delete"}
},
"required": ["fileId"]
}
),
Tool(
name="search_files",
description="Search for files in Google Drive",
inputSchema={
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query (e.g., \"name contains 'report'\", \"mimeType='application/pdf'\")"
},
"maxResults": {"type": "integer", "default": 50}
},
"required": ["query"]
}
),
Tool(
name="share_file",
description="Share a file or folder with a user",
inputSchema={
"type": "object",
"properties": {
"fileId": {"type": "string"},
"email": {"type": "string"},
"role": {"type": "string", "enum": ["reader", "writer", "commenter"], "default": "reader"},
"sendNotification": {"type": "boolean", "default": True}
},
"required": ["fileId", "email"]
}
),
Tool(
name="share_file_with_anyone",
description="Share a file with anyone who has the link",
inputSchema={
"type": "object",
"properties": {
"fileId": {"type": "string"},
"role": {"type": "string", "enum": ["reader", "writer"], "default": "reader"}
},
"required": ["fileId"]
}
),
Tool(
name="get_file_metadata",
description="Get detailed metadata about a file",
inputSchema={
"type": "object",
"properties": {
"fileId": {"type": "string"}
},
"required": ["fileId"]
}
),
Tool(
name="rename_file",
description="Rename a file or folder",
inputSchema={
"type": "object",
"properties": {
"fileId": {"type": "string"},
"newName": {"type": "string"}
},
"required": ["fileId", "newName"]
}
),
Tool(
name="get_storage_quota",
description="Get Google Drive storage quota information",
inputSchema={
"type": "object",
"properties": {}
}
),
Tool(
name="export_to_drive",
description="Export content to a file in Google Drive",
inputSchema={
"type": "object",
"properties": {
"fileName": {"type": "string"},
"content": {"type": "string"},
"folderId": {"type": "string", "description": "Optional destination folder"},
"mimeType": {"type": "string", "default": "text/plain"}
},
"required": ["fileName", "content"]
}
),
# ==================== LOCAL STORAGE TOOLS ====================
Tool(
name="set_profile",
description="Set a personal profile field (name, email, phone, linkedin, github, summary, etc.)",
inputSchema={
"type": "object",
"properties": {
"field": {"type": "string", "description": "Field name (e.g., 'name', 'email', 'phone', 'linkedin')"},
"value": {"type": "string", "description": "Field value"}
},
"required": ["field", "value"]
}
),
Tool(
name="get_profile",
description="Get personal profile information",
inputSchema={
"type": "object",
"properties": {
"field": {"type": "string", "description": "Specific field to get (optional, returns all if not specified)"}
}
}
),
Tool(
name="get_full_profile",
description="Get complete profile with skills, experience, and education",
inputSchema={
"type": "object",
"properties": {}
}
),
Tool(
name="add_job_application",
description="Add a new job application to track",
inputSchema={
"type": "object",
"properties": {
"company": {"type": "string"},
"position": {"type": "string"},
"location": {"type": "string"},
"salaryRange": {"type": "string"},
"jobUrl": {"type": "string"},
"dateApplied": {"type": "string", "description": "Date in YYYY-MM-DD format"},
"status": {"type": "string", "enum": ["applied", "screening", "interviewing", "offer", "rejected", "withdrawn"]},
"contactName": {"type": "string"},
"contactEmail": {"type": "string"},
"notes": {"type": "string"}
},
"required": ["company", "position"]
}
),
Tool(
name="get_job_applications",
description="Get job applications with optional filters",
inputSchema={
"type": "object",
"properties": {
"status": {"type": "string"},
"company": {"type": "string"},
"limit": {"type": "integer", "default": 50}
}
}
),
Tool(
name="update_job_application",
description="Update a job application",
inputSchema={
"type": "object",
"properties": {
"applicationId": {"type": "integer"},
"status": {"type": "string"},
"notes": {"type": "string"},
"followUpDate": {"type": "string"}
},
"required": ["applicationId"]
}
),
Tool(
name="add_interview",
description="Add an interview for a job application",
inputSchema={
"type": "object",
"properties": {
"applicationId": {"type": "integer"},
"interviewDate": {"type": "string", "description": "Date/time in ISO format"},
"interviewType": {"type": "string", "description": "phone, video, onsite, technical, etc."},
"interviewerName": {"type": "string"},
"interviewerEmail": {"type": "string"},
"notes": {"type": "string"}
},
"required": ["applicationId", "interviewDate", "interviewType"]
}
),
Tool(
name="get_interviews",
description="Get interviews with optional filters",
inputSchema={
"type": "object",
"properties": {
"applicationId": {"type": "integer"},
"status": {"type": "string"},
"upcomingOnly": {"type": "boolean", "default": False}
}
}
),
Tool(
name="add_contact",
description="Add a networking contact",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"phone": {"type": "string"},
"company": {"type": "string"},
"title": {"type": "string"},
"linkedinUrl": {"type": "string"},
"relationship": {"type": "string"},
"notes": {"type": "string"}
},
"required": ["name"]
}
),
Tool(
name="get_contacts",
description="Get networking contacts",
inputSchema={
"type": "object",
"properties": {
"company": {"type": "string"},
"search": {"type": "string"}
}
}
),
Tool(
name="add_skill",
description="Add a skill to your profile",
inputSchema={
"type": "object",
"properties": {
"skillName": {"type": "string"},
"category": {"type": "string", "description": "e.g., programming, framework, tool, soft skill"},
"proficiency": {"type": "string", "enum": ["beginner", "intermediate", "advanced", "expert"]},
"yearsExperience": {"type": "integer"}
},
"required": ["skillName"]
}
),
Tool(
name="get_skills",
description="Get all skills, optionally filtered by category",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string"}
}
}
),
Tool(
name="add_work_experience",
description="Add work experience to your profile",
inputSchema={
"type": "object",
"properties": {
"company": {"type": "string"},
"title": {"type": "string"},
"startDate": {"type": "string"},
"endDate": {"type": "string"},
"isCurrent": {"type": "boolean"},
"description": {"type": "string"},
"achievements": {"type": "string"},
"technologies": {"type": "string"}
},
"required": ["company", "title"]
}
),
Tool(
name="get_work_experience",
description="Get all work experience",
inputSchema={
"type": "object",
"properties": {}
}
),
Tool(
name="add_education",
description="Add education to your profile",
inputSchema={
"type": "object",
"properties": {
"institution": {"type": "string"},
"degree": {"type": "string"},
"fieldOfStudy": {"type": "string"},
"startDate": {"type": "string"},
"endDate": {"type": "string"},
"gpa": {"type": "string"},
"achievements": {"type": "string"}
},
"required": ["institution"]
}
),
Tool(
name="get_education",
description="Get all education entries",
inputSchema={
"type": "object",
"properties": {}
}
),
Tool(
name="add_task",
description="Add a task or reminder",
inputSchema={
"type": "object",
"properties": {
"title": {"type": "string"},
"description": {"type": "string"},
"dueDate": {"type": "string"},
"priority": {"type": "string", "enum": ["low", "medium", "high"]},
"category": {"type": "string"},
"relatedApplicationId": {"type": "integer"}
},
"required": ["title"]
}
),
Tool(
name="get_tasks",
description="Get tasks/reminders",
inputSchema={
"type": "object",
"properties": {
"status": {"type": "string"},
"category": {"type": "string"},
"includeCompleted": {"type": "boolean", "default": False}
}
}
),
Tool(
name="complete_task",
description="Mark a task as completed",
inputSchema={
"type": "object",
"properties": {
"taskId": {"type": "integer"}
},
"required": ["taskId"]
}
),
Tool(
name="add_note",
description="Add a note",
inputSchema={
"type": "object",
"properties": {
"content": {"type": "string"},
"title": {"type": "string"},
"category": {"type": "string"},
"tags": {"type": "array", "items": {"type": "string"}}
},
"required": ["content"]
}
),
Tool(
name="get_notes",
description="Get notes with optional filters",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string"},
"search": {"type": "string"}
}
}
),
Tool(
name="add_email_template",
description="Add an email template for reuse",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string"},
"subject": {"type": "string"},
"body": {"type": "string"},
"templateType": {"type": "string", "description": "e.g., followup, thankyou, introduction"}
},
"required": ["name", "body"]
}
),
Tool(
name="get_email_template",
description="Get an email template by name",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string"}
},
"required": ["name"]
}
),
Tool(
name="list_email_templates",
description="List all email templates",
inputSchema={
"type": "object",
"properties": {
"templateType": {"type": "string"}
}
}
),
Tool(
name="get_job_search_summary",
description="Get summary statistics of your job search",
inputSchema={
"type": "object",
"properties": {}
}
),
# ==================== MEMORY SYSTEM TOOLS ====================
# These tools store EVERYTHING about the user - who they are, what they do, how they do it
Tool(
name="save_about_me",
description="Save any information about the user. Use this when user says 'save this', 'remember this', or shares personal info. Categories: personal, professional, contact, preferences, facts",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string", "description": "Category: personal, professional, contact, preferences, facts"},
"key": {"type": "string", "description": "What this info is about (e.g., 'name', 'email', 'favorite_tool')"},
"value": {"type": "string", "description": "The actual information to save"}
},
"required": ["category", "key", "value"]
}
),
Tool(
name="get_about_me",
description="Get stored information about the user. Use this FIRST before answering questions about the user.",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string", "description": "Optional: filter by category"}
}
}
),
Tool(
name="remember",
description="Quickly remember anything - facts, preferences, notes, temporary info. Use for any 'save this' or 'remember this' request.",
inputSchema={
"type": "object",
"properties": {
"topic": {"type": "string", "description": "What this is about"},
"content": {"type": "string", "description": "The information to remember"},
"tags": {"type": "array", "items": {"type": "string"}, "description": "Optional tags"},
"importance": {"type": "string", "enum": ["low", "normal", "high"], "default": "normal"}
},
"required": ["topic", "content"]
}
),
Tool(
name="recall",
description="Recall stored memories. Search by topic, tags, or keyword.",
inputSchema={
"type": "object",
"properties": {
"topic": {"type": "string"},
"tags": {"type": "string"},
"search": {"type": "string", "description": "Keyword search"}
}
}
),
Tool(
name="add_behavior",
description="Store how the user does things - work habits, patterns, approaches",
inputSchema={
"type": "object",
"properties": {
"behavior_type": {"type": "string", "description": "Type: work, communication, decision_making, problem_solving, learning"},
"description": {"type": "string", "description": "Description of the behavior"},
"context": {"type": "string"},
"frequency": {"type": "string"},
"importance": {"type": "string", "enum": ["low", "medium", "high"], "default": "medium"}
},
"required": ["behavior_type", "description"]
}
),
Tool(
name="get_behaviors",
description="Get stored behavior patterns",
inputSchema={
"type": "object",
"properties": {
"behavior_type": {"type": "string"}
}
}
),
Tool(
name="add_preference",
description="Store user preferences - what they like/dislike, how they want things done",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string", "description": "Category: tools, communication, work, lifestyle, technology"},
"preference": {"type": "string", "description": "The preference"},
"value": {"type": "string"},
"reason": {"type": "string"},
"priority": {"type": "integer", "default": 5}
},
"required": ["category", "preference"]
}
),
Tool(
name="get_preferences",
description="Get stored preferences",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string"}
}
}
),
Tool(
name="add_goal",
description="Store user goals and objectives",
inputSchema={
"type": "object",
"properties": {
"goal_type": {"type": "string", "description": "Type: career, learning, health, financial, personal, project"},
"description": {"type": "string"},
"timeframe": {"type": "string"},
"priority": {"type": "string", "enum": ["low", "medium", "high"]},
"milestones": {"type": "string"}
},
"required": ["goal_type", "description"]
}
),
Tool(
name="get_goals",
description="Get stored goals",
inputSchema={
"type": "object",
"properties": {
"goal_type": {"type": "string"},
"status": {"type": "string", "default": "active"}
}
}
),
Tool(
name="add_work_style",
description="Store how the user works - time management, focus, collaboration style",
inputSchema={
"type": "object",
"properties": {
"aspect": {"type": "string", "description": "Aspect: time_management, focus, collaboration, communication, tools, environment"},
"description": {"type": "string"},
"examples": {"type": "string"},
"tips_for_ai": {"type": "string", "description": "How AI should adapt to this style"}
},
"required": ["aspect", "description"]
}
),
Tool(
name="get_work_style",
description="Get stored work style preferences",
inputSchema={
"type": "object",
"properties": {
"aspect": {"type": "string"}
}
}
),
Tool(
name="add_fact",
description="Store a factual piece of information about the user",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string", "description": "Category: personal, professional, education, achievement, certification"},
"fact": {"type": "string"},
"context": {"type": "string"},
"source": {"type": "string"}
},
"required": ["category", "fact"]
}
),
Tool(
name="get_facts",
description="Get stored facts about the user",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string"},
"search": {"type": "string"}
}
}
),
Tool(
name="add_pattern",
description="Store a recurring pattern the user follows",
inputSchema={
"type": "object",
"properties": {
"pattern_type": {"type": "string", "description": "Type: daily, weekly, work, personal, seasonal, situational"},
"description": {"type": "string"},
"trigger": {"type": "string"},
"frequency": {"type": "string"},
"time_context": {"type": "string"}
},
"required": ["pattern_type", "description"]
}
),
Tool(
name="get_patterns",
description="Get stored patterns",
inputSchema={
"type": "object",
"properties": {
"pattern_type": {"type": "string"}
}
}
),
Tool(
name="add_decision_style",
description="Store how the user makes decisions in different areas",
inputSchema={
"type": "object",
"properties": {
"decision_area": {"type": "string", "description": "Area: career, financial, technical, personal, work, purchases"},
"approach": {"type": "string"},
"factors": {"type": "string"},
"examples": {"type": "string"}
},
"required": ["decision_area", "approach"]
}
),
Tool(
name="get_decision_styles",
description="Get stored decision-making styles",
inputSchema={
"type": "object",
"properties": {
"decision_area": {"type": "string"}
}
}
),
Tool(
name="log_interaction",
description="Log an interaction or activity with the user",
inputSchema={
"type": "object",
"properties": {
"interaction_type": {"type": "string", "description": "Type: conversation, task, decision, meeting, research, project"},
"summary": {"type": "string"},
"details": {"type": "string"},
"outcome": {"type": "string"},
"learnings": {"type": "string"}
},
"required": ["interaction_type", "summary"]
}
),
Tool(
name="get_interactions",
description="Get logged interactions",
inputSchema={
"type": "object",
"properties": {
"interaction_type": {"type": "string"},
"limit": {"type": "integer", "default": 50}
}
}
),
Tool(
name="learn_about_user",
description="Log something new learned about the user during conversation",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string", "description": "Category: preference, behavior, style, fact, pattern"},
"learned": {"type": "string"},
"context": {"type": "string"},
"confidence": {"type": "string", "enum": ["low", "medium", "high"], "default": "medium"}
},
"required": ["category", "learned"]
}
),
Tool(
name="get_learnings",
description="Get things learned about the user",
inputSchema={
"type": "object",
"properties": {
"category": {"type": "string"},
"limit": {"type": "integer", "default": 50}
}
}
),
Tool(
name="get_everything_about_user",
description="Get ALL stored information about the user - complete memory dump. Use this at start of conversations.",
inputSchema={
"type": "object",
"properties": {}
}
),
Tool(
name="search_memory",
description="Search across all memory for a term",
inputSchema={
"type": "object",
"properties": {
"search_term": {"type": "string"}
},
"required": ["search_term"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
start_time = datetime.now()
logger.info(f"TOOL CALL START: {name}")
logger.debug(f"Arguments: {json.dumps(arguments, default=str)}")
try:
result = None
# ==================== SHEETS ====================
if name == "create_spreadsheet":
result = sheets.create_spreadsheet(
arguments["title"],
arguments.get("sheetNames")
)
elif name == "read_sheet":
spreadsheet_id = arguments.get("spreadsheetId") or config.get("google", {}).get("spreadsheetId")
result = sheets.read_sheet_data(spreadsheet_id, arguments["range"])
elif name == "write_sheet":
spreadsheet_id = arguments.get("spreadsheetId") or config.get("google", {}).get("spreadsheetId")
result = sheets.write_sheet_data(spreadsheet_id, arguments["range"], arguments["values"])
elif name == "append_sheet":
spreadsheet_id = arguments.get("spreadsheetId") or config.get("google", {}).get("spreadsheetId")
result = sheets.append_sheet_data(spreadsheet_id, arguments["range"], arguments["values"])
elif name == "get_sheet_info":
spreadsheet_id = arguments.get("spreadsheetId") or config.get("google", {}).get("spreadsheetId")
result = sheets.get_sheet_info(spreadsheet_id)
elif name == "create_sheet_tab":
result = sheets.create_sheet_tab(arguments["spreadsheetId"], arguments["tabName"])
elif name == "list_spreadsheets":
result = sheets.list_spreadsheets(arguments.get("maxResults", 50))
elif name == "format_cells":
result = sheets.format_cells(
arguments["spreadsheetId"],
arguments["range"],
arguments["formatOptions"]
)
elif name == "add_formula":
result = sheets.add_formula(
arguments["spreadsheetId"],
arguments["cell"],
arguments["formula"]
)
elif name == "share_spreadsheet":
result = sheets.share_spreadsheet(
arguments["spreadsheetId"],
arguments["email"],
arguments.get("role", "reader")
)
elif name == "create_job_tracker":
result = sheets.create_job_tracker(arguments.get("title", "Job Applications Tracker"))
# ==================== GMAIL ====================
elif name == "list_emails":
result = gmail.list_emails(arguments.get("maxResults", 10), arguments.get("query", ""))
elif name == "get_email_detail":
result = gmail.get_email_detail(arguments["messageId"])
elif name == "send_email":
result = gmail.send_email(
arguments["to"],
arguments["subject"],
arguments["body"],
arguments.get("isHtml", False)
)
elif name == "search_emails":
result = gmail.search_emails(arguments["query"])
elif name == "create_draft":
result = gmail.create_draft(
arguments["to"],
arguments["subject"],
arguments["body"],
arguments.get("isHtml", False),
arguments.get("cc"),
arguments.get("bcc")
)
elif name == "list_drafts":
result = gmail.list_drafts(arguments.get("maxResults", 20))
elif name == "get_draft":
result = gmail.get_draft(arguments["draftId"])
elif name == "update_draft":
result = gmail.update_draft(
arguments["draftId"],
arguments.get("to"),
arguments.get("subject"),
arguments.get("body"),
arguments.get("isHtml", False)
)
elif name == "send_draft":
result = gmail.send_draft(arguments["draftId"])
elif name == "delete_draft":
result = gmail.delete_draft(arguments["draftId"])
elif name == "reply_to_email":
result = gmail.reply_to_email(
arguments["messageId"],
arguments["body"],
arguments.get("isHtml", False)
)
elif name == "forward_email":
result = gmail.forward_email(
arguments["messageId"],
arguments["to"],
arguments.get("additionalMessage", "")
)
elif name == "add_label":
result = gmail.add_label(arguments["messageId"], arguments["labelName"])
elif name == "list_labels":
result = gmail.list_labels()
elif name == "trash_email":
result = gmail.trash_email(arguments["messageId"])
elif name == "archive_email":
result = gmail.archive_email(arguments["messageId"])
elif name == "create_followup_draft":
result = gmail.create_followup_draft(
arguments["companyName"],
arguments["contactName"],
arguments["position"],
arguments.get("daysSinceApplication", 7)
)
elif name == "create_thank_you_draft":
result = gmail.create_thank_you_draft(
arguments["interviewerName"],
arguments["companyName"],
arguments["position"],
arguments.get("interviewTopics")
)
# ==================== CALENDAR ====================
elif name == "list_calendar_events":
result = calendar.list_events(
arguments.get("calendarId") or config.get("google", {}).get("calendarId", "primary"),
arguments.get("maxResults", 10),
arguments.get("timeMin")
)
elif name == "create_calendar_event":
result = calendar.create_event(
arguments.get("calendarId") or config.get("google", {}).get("calendarId", "primary"),
{
"summary": arguments["summary"],
"description": arguments.get("description", ""),
"start": arguments["start"],
"end": arguments["end"],
"location": arguments.get("location", ""),
"attendees": arguments.get("attendees", []),
"timeZone": arguments.get("timeZone", "America/Los_Angeles")
}
)
elif name == "update_calendar_event":
result = calendar.update_event(
arguments.get("calendarId") or config.get("google", {}).get("calendarId", "primary"),
arguments["eventId"],
{
"summary": arguments.get("summary"),
"description": arguments.get("description"),
"start": arguments.get("start"),
"end": arguments.get("end"),
"location": arguments.get("location"),
"attendees": arguments.get("attendees"),
"timeZone": arguments.get("timeZone", "America/Los_Angeles")
}
)
elif name == "delete_calendar_event":
result = calendar.delete_event(
arguments.get("calendarId") or config.get("google", {}).get("calendarId", "primary"),
arguments["eventId"]
)
elif name == "get_calendar_event":
result = calendar.get_event(
arguments.get("calendarId") or config.get("google", {}).get("calendarId", "primary"),
arguments["eventId"]
)
# ==================== DOCS ====================
elif name == "create_document":
result = docs.create_document(
arguments["title"],
arguments.get("initialContent")
)
elif name == "read_document":
result = docs.read_document(arguments["documentId"])
elif name == "append_to_document":
result = docs.append_to_document(arguments["documentId"], arguments["content"])
elif name == "format_document_text":
result = docs.format_text(
arguments["documentId"],
arguments["startIndex"],
arguments["endIndex"],
arguments["formatOptions"]
)
elif name == "apply_paragraph_style":
result = docs.apply_paragraph_style(
arguments["documentId"],
arguments["startIndex"],
arguments["endIndex"],
arguments["styleOptions"]
)
elif name == "insert_table":
result = docs.insert_table(
arguments["documentId"],
arguments["rows"],
arguments["cols"],
arguments.get("data"),
arguments.get("index")
)
elif name == "insert_bullet_list":
result = docs.insert_bullet_list(
arguments["documentId"],
arguments["items"],
arguments.get("index")
)
elif name == "insert_numbered_list":
result = docs.insert_numbered_list(
arguments["documentId"],
arguments["items"],
arguments.get("index")
)
elif name == "list_documents":
result = docs.list_documents(arguments.get("maxResults", 50))
elif name == "share_document":
result = docs.share_document(
arguments["documentId"],
arguments["email"],
arguments.get("role", "reader")
)
elif name == "create_daily_report":
result = docs.create_daily_report(
arguments.get("title"),
arguments.get("sections")
)
# ==================== DRIVE ====================
elif name == "list_files":
result = drive.list_files(
arguments.get("folderId"),
arguments.get("query"),
arguments.get("maxResults", 50)
)
elif name == "list_folders":
result = drive.list_folders(
arguments.get("parentFolderId"),
arguments.get("maxResults", 50)
)
elif name == "create_folder":
result = drive.create_folder(
arguments["name"],
arguments.get("parentFolderId")
)
elif name == "upload_file":
result = drive.upload_file(
arguments["name"],
arguments["content"],
arguments.get("mimeType", "text/plain"),
arguments.get("folderId")
)
elif name == "download_file":
result = drive.download_file(arguments["fileId"])
elif name == "move_file":
result = drive.move_file(arguments["fileId"], arguments["newFolderId"])
elif name == "copy_file":
result = drive.copy_file(
arguments["fileId"],
arguments.get("newName"),
arguments.get("folderId")
)
elif name == "delete_file":
result = drive.delete_file(arguments["fileId"])
elif name == "search_files":
result = drive.search_files(
arguments["query"],
arguments.get("maxResults", 50)
)
elif name == "share_file":
result = drive.share_file(
arguments["fileId"],
arguments["email"],
arguments.get("role", "reader"),
arguments.get("sendNotification", True)
)
elif name == "share_file_with_anyone":
result = drive.share_file_with_anyone(
arguments["fileId"],
arguments.get("role", "reader")
)
elif name == "get_file_metadata":
result = drive.get_file_metadata(arguments["fileId"])
elif name == "rename_file":
result = drive.rename_file(arguments["fileId"], arguments["newName"])
elif name == "get_storage_quota":
result = drive.get_storage_quota()
elif name == "export_to_drive":
result = drive.export_to_drive(
arguments["fileName"],
arguments["content"],
arguments.get("folderId"),
arguments.get("mimeType", "text/plain")
)
# ==================== LOCAL STORAGE ====================
elif name == "set_profile":
result = storage.set_profile(arguments["field"], arguments["value"])
elif name == "get_profile":
result = storage.get_profile(arguments.get("field"))
elif name == "get_full_profile":
result = storage.get_full_profile()
elif name == "add_job_application":
kwargs = {}
if "location" in arguments:
kwargs["location"] = arguments["location"]
if "salaryRange" in arguments:
kwargs["salary_range"] = arguments["salaryRange"]
if "jobUrl" in arguments:
kwargs["job_url"] = arguments["jobUrl"]
if "dateApplied" in arguments:
kwargs["date_applied"] = arguments["dateApplied"]
if "status" in arguments:
kwargs["status"] = arguments["status"]
if "contactName" in arguments:
kwargs["contact_name"] = arguments["contactName"]
if "contactEmail" in arguments:
kwargs["contact_email"] = arguments["contactEmail"]
if "notes" in arguments:
kwargs["notes"] = arguments["notes"]
result = storage.add_job_application(
arguments["company"],
arguments["position"],
**kwargs
)
elif name == "get_job_applications":
result = storage.get_job_applications(
arguments.get("status"),
arguments.get("company"),
arguments.get("limit", 50)
)
elif name == "update_job_application":
kwargs = {}
if "status" in arguments:
kwargs["status"] = arguments["status"]
if "notes" in arguments:
kwargs["notes"] = arguments["notes"]
if "followUpDate" in arguments:
kwargs["follow_up_date"] = arguments["followUpDate"]
result = storage.update_job_application(arguments["applicationId"], **kwargs)
elif name == "add_interview":
kwargs = {}
if "interviewerName" in arguments:
kwargs["interviewer_name"] = arguments["interviewerName"]
if "interviewerEmail" in arguments:
kwargs["interviewer_email"] = arguments["interviewerEmail"]
if "notes" in arguments:
kwargs["notes"] = arguments["notes"]
result = storage.add_interview(
arguments["applicationId"],
arguments["interviewDate"],
arguments["interviewType"],
**kwargs
)
elif name == "get_interviews":
result = storage.get_interviews(
arguments.get("applicationId"),
arguments.get("status"),
arguments.get("upcomingOnly", False)
)
elif name == "add_contact":
kwargs = {}
for field in ["email", "phone", "company", "title", "relationship", "notes"]:
if field in arguments:
kwargs[field] = arguments[field]
if "linkedinUrl" in arguments:
kwargs["linkedin_url"] = arguments["linkedinUrl"]
result = storage.add_contact(arguments["name"], **kwargs)
elif name == "get_contacts":
result = storage.get_contacts(
arguments.get("company"),
arguments.get("search")
)
elif name == "add_skill":
result = storage.add_skill(
arguments["skillName"],
arguments.get("category"),
arguments.get("proficiency"),
arguments.get("yearsExperience")
)
elif name == "get_skills":
result = storage.get_skills(arguments.get("category"))
elif name == "add_work_experience":
kwargs = {}
if "startDate" in arguments:
kwargs["start_date"] = arguments["startDate"]
if "endDate" in arguments:
kwargs["end_date"] = arguments["endDate"]
if "isCurrent" in arguments:
kwargs["is_current"] = arguments["isCurrent"]
if "description" in arguments:
kwargs["description"] = arguments["description"]
if "achievements" in arguments:
kwargs["achievements"] = arguments["achievements"]
if "technologies" in arguments:
kwargs["technologies"] = arguments["technologies"]
result = storage.add_work_experience(
arguments["company"],
arguments["title"],
**kwargs
)
elif name == "get_work_experience":
result = storage.get_work_experience()
elif name == "add_education":
kwargs = {}
for field in ["degree", "gpa", "achievements"]:
if field in arguments:
kwargs[field] = arguments[field]
if "fieldOfStudy" in arguments:
kwargs["field_of_study"] = arguments["fieldOfStudy"]
if "startDate" in arguments:
kwargs["start_date"] = arguments["startDate"]
if "endDate" in arguments:
kwargs["end_date"] = arguments["endDate"]
result = storage.add_education(arguments["institution"], **kwargs)
elif name == "get_education":
result = storage.get_education()
elif name == "add_task":
kwargs = {}
if "description" in arguments:
kwargs["description"] = arguments["description"]
if "dueDate" in arguments:
kwargs["due_date"] = arguments["dueDate"]
if "priority" in arguments:
kwargs["priority"] = arguments["priority"]
if "category" in arguments:
kwargs["category"] = arguments["category"]
if "relatedApplicationId" in arguments:
kwargs["related_application_id"] = arguments["relatedApplicationId"]
result = storage.add_task(arguments["title"], **kwargs)
elif name == "get_tasks":
result = storage.get_tasks(
arguments.get("status"),
arguments.get("category"),
arguments.get("includeCompleted", False)
)
elif name == "complete_task":
result = storage.complete_task(arguments["taskId"])
elif name == "add_note":
result = storage.add_note(
arguments["content"],
arguments.get("title"),
arguments.get("category"),
arguments.get("tags")
)
elif name == "get_notes":
result = storage.get_notes(
arguments.get("category"),
arguments.get("search")
)
elif name == "add_email_template":
result = storage.add_email_template(
arguments["name"],
arguments["body"],
arguments.get("subject"),
arguments.get("templateType")
)
elif name == "get_email_template":
result = storage.get_email_template(arguments["name"])
elif name == "list_email_templates":
result = storage.list_email_templates(arguments.get("templateType"))
elif name == "get_job_search_summary":
result = storage.get_job_search_summary()
# ==================== MEMORY SYSTEM ====================
elif name == "save_about_me":
result = memory.set_identity(
arguments["category"],
arguments["key"],
arguments["value"]
)
elif name == "get_about_me":
result = memory.get_identity(arguments.get("category"))
elif name == "remember":
result = memory.remember(
arguments["topic"],
arguments["content"],
arguments.get("tags"),
arguments.get("importance", "normal")
)
elif name == "recall":
result = memory.recall(
arguments.get("topic"),
arguments.get("tags"),
arguments.get("search")
)
elif name == "add_behavior":
result = memory.add_behavior(
arguments["behavior_type"],
arguments["description"],
arguments.get("context"),
arguments.get("frequency"),
arguments.get("importance", "medium"),
arguments.get("examples")
)
elif name == "get_behaviors":
result = memory.get_behaviors(arguments.get("behavior_type"))
elif name == "add_preference":
result = memory.add_preference(
arguments["category"],
arguments["preference"],
arguments.get("value"),
arguments.get("reason"),
arguments.get("priority", 5)
)
elif name == "get_preferences":
result = memory.get_preferences(arguments.get("category"))
elif name == "add_goal":
result = memory.add_goal(
arguments["goal_type"],
arguments["description"],
arguments.get("timeframe"),
arguments.get("priority", "medium"),
arguments.get("milestones")
)
elif name == "get_goals":
result = memory.get_goals(
arguments.get("goal_type"),
arguments.get("status", "active")
)
elif name == "add_work_style":
result = memory.add_work_style(
arguments["aspect"],
arguments["description"],
arguments.get("examples"),
arguments.get("tips_for_ai")
)
elif name == "get_work_style":
result = memory.get_work_style(arguments.get("aspect"))
elif name == "add_fact":
result = memory.add_fact(
arguments["category"],
arguments["fact"],
arguments.get("context"),
arguments.get("source")
)
elif name == "get_facts":
result = memory.get_facts(
arguments.get("category"),
arguments.get("search")
)
elif name == "add_pattern":
result = memory.add_pattern(
arguments["pattern_type"],
arguments["description"],
arguments.get("trigger"),
arguments.get("frequency"),
arguments.get("time_context"),
arguments.get("notes")
)
elif name == "get_patterns":
result = memory.get_patterns(arguments.get("pattern_type"))
elif name == "add_decision_style":
result = memory.add_decision_style(
arguments["decision_area"],
arguments["approach"],
arguments.get("factors"),
arguments.get("examples")
)
elif name == "get_decision_styles":
result = memory.get_decision_styles(arguments.get("decision_area"))
elif name == "log_interaction":
result = memory.log_interaction(
arguments["interaction_type"],
arguments["summary"],
arguments.get("details"),
arguments.get("outcome"),
arguments.get("learnings")
)
elif name == "get_interactions":
result = memory.get_interactions(
arguments.get("interaction_type"),
arguments.get("limit", 50)
)
elif name == "learn_about_user":
result = memory.learn_about_user(
arguments["category"],
arguments["learned"],
arguments.get("context"),
arguments.get("confidence", "medium")
)
elif name == "get_learnings":
result = memory.get_learnings(
arguments.get("category"),
arguments.get("limit", 50)
)
elif name == "get_everything_about_user":
result = memory.get_everything_about_user()
elif name == "search_memory":
result = memory.search_all_memory(arguments["search_term"])
else:
result = {"success": False, "error": f"Unknown tool: {name}"}
logger.warning(f"Unknown tool requested: {name}")
# Log result
duration = (datetime.now() - start_time).total_seconds()
success = result.get('success', False) if isinstance(result, dict) else False
if success:
logger.info(f"TOOL CALL END: {name} | SUCCESS | Duration: {duration:.3f}s")
else:
error_msg = result.get('error', 'Unknown error') if isinstance(result, dict) else str(result)
logger.error(f"TOOL CALL END: {name} | FAILED | Duration: {duration:.3f}s | Error: {error_msg}")
return [TextContent(type="text", text=json.dumps(result, indent=2))]
except KeyError as e:
duration = (datetime.now() - start_time).total_seconds()
error_msg = f"Missing required argument: {e}"
logger.error(f"TOOL CALL END: {name} | FAILED | Duration: {duration:.3f}s | Error: {error_msg}")
logger.debug(f"Traceback:\n{traceback.format_exc()}")
return [TextContent(type="text", text=json.dumps({"success": False, "error": error_msg}, indent=2))]
except Exception as error:
duration = (datetime.now() - start_time).total_seconds()
error_msg = str(error)
logger.error(f"TOOL CALL END: {name} | EXCEPTION | Duration: {duration:.3f}s | Error: {error_msg}")
logger.debug(f"Traceback:\n{traceback.format_exc()}")
return [TextContent(type="text", text=json.dumps({"success": False, "error": error_msg}, indent=2))]
async def main():
from mcp.server.stdio import stdio_server
logger.info("Starting MCP server with stdio transport")
try:
async with stdio_server() as (read_stream, write_stream):
logger.info("Server connected, running...")
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
except Exception as e:
logger.error(f"Server error: {e}")
logger.debug(f"Traceback:\n{traceback.format_exc()}")
raise
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
logger.info("Server stopped by user")
except Exception as e:
logger.error(f"Fatal error: {e}")
logger.debug(f"Traceback:\n{traceback.format_exc()}")