Skip to content

function0llc/fx0-mcp-server

Repository files navigation

FX0 MCP Server

A production-ready Model Context Protocol (MCP) server that exposes Microsoft Graph capabilities for Email, Calendar, To Do (Reminders), and Google Custom Search. (Other tools comming soon!) This server supports both STDIO and HTTP transport modes. Can be run local or in Docker.

Python 3.11+ License: MIT Code style: black

πŸš€ Features

  • Email Management: List, search, send, reply, forward messages with attachment support
  • Calendar Integration: Event management, meeting scheduling, availability checks
  • Web Search: Google Custom Search API integration for web information retrieval
  • File Utilities (fx0.tool.write_*): Write TXT, CSV, DOCX, XLSX, PDF, and PPTX files to the server temp directory
  • To Do Lists: Task creation, management, and tracking with due dates
  • Microsoft Teams: Channel/chat messaging, presence lookup, meeting creation
  • SharePoint/OneDrive: File discovery, uploads/downloads, sharing links
  • Auth Tools: Device code login initiation, polling, status, logout
  • Production Ready: OAuth2 with MSAL, encrypted token caching, comprehensive error handling
  • Multiple Transports: STDIO (primary) and HTTP/SSE support
  • Observability: Structured logging, correlation IDs, optional OpenTelemetry integration

πŸ—οΈ Architecture

  • Authentication: Delegated user flow via device code (default) with encrypted per-user token cache
  • Fallback Auth: Optional confidential client mode for service scenarios
  • Transports: STDIO for MCP clients + HTTP/SSE for web integration
  • Resilience: Exponential backoff, circuit breaker, rate limit handling
  • Security: Least-privilege scopes, PII redaction, SSRF protection

πŸ“¦ Installation

From PyPI (Coming Soon)

pip install fx0-mcp-server

From Source

git clone https://github.com/your-org/fx0-mcp-server.git
cd fx0-mcp-server
pip install -e .

With Optional Dependencies

# For development
pip install -e ".[dev]"

# For OpenTelemetry support
pip install -e ".[telemetry]"

# For keyring integration
pip install -e ".[keyring]"

# For Google Search API support (google.tool.search)
pip install google-api-python-client

# For File Utilities (optional format libraries)
# TXT/CSV require no extras. For others, install as needed:
# DOCX  -> pip install python-docx
# XLSX  -> pip install openpyxl
# PDF   -> pip install reportlab
# PPTX  -> pip install python-pptx

βš™οΈ Configuration

Environment Variables

Copy dot_env.example to .env and configure:

# Required - Azure App Registration (Delegated Flow)
TENANT_ID=your-tenant-id
CLIENT_ID=your-client-id

# Microsoft Graph Configuration
GRAPH_BASE_URL=https://graph.microsoft.com/v1.0
AUTHORITY=https://login.microsoftonline.com/{tenant}

# Scopes (space-separated, minimal per domain)
SCOPES="Mail.Read Mail.Send Calendars.ReadWrite Tasks.ReadWrite Chat.ReadWrite Files.ReadWrite offline_access"

# Google Search Configuration (Optional - for google.tool.search)
GOOGLE_SEARCH_API_KEY=your-google-search-api-key
GOOGLE_SEARCH_ENGINE_ID=your-custom-search-engine-id

# Transport Configuration
TRANSPORT=stdio  # or "http"
HOST=127.0.0.1   # HTTP only
PORT=8000        # HTTP only
SSE_ENABLED=true # HTTP only

# Optional - Confidential Client Mode
# CLIENT_SECRET=your-client-secret
# AUTH_MODE=confidential

# Logging and Observability
LOG_LEVEL=INFO
LOG_FORMAT=json
# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

# Token Cache
TOKEN_CACHE=~/.fx0_cache/token_cache.bin
# TOKEN_CACHE=redis://localhost:6379/0
# CACHE_ENCRYPTION_KEY=your-encryption-key

Azure App Registration Setup

For Delegated Flow (Default)

  1. Register app in Azure Portal
  2. Authentication β†’ Add platform β†’ Mobile and desktop applications
  3. Add redirect URI: http://localhost
  4. API permissions β†’ Add permissions β†’ Microsoft Graph β†’ Delegated permissions
  5. Add minimal scopes per domain:
    • Mail.Read, Mail.Send (Email)
    • Calendars.ReadWrite (Calendar)
    • Tasks.ReadWrite (To Do)
    • Chat.ReadWrite, ChannelMessage.Send (Teams)
    • Files.ReadWrite (SharePoint/OneDrive)
    • offline_access (Token refresh)
  6. Grant admin consent (if required by organization)

Google Search API Setup (Optional - for google.tool.search)

  1. Go to the Google Cloud Console
  2. Create a new project or select an existing one
  3. Enable the Custom Search API
  4. Create credentials (API key) for the Custom Search API
  5. Set up a Custom Search Engine
  6. Configure your search engine and note the Search Engine ID
  7. Set the environment variables:
    • GOOGLE_SEARCH_API_KEY: Your Google API key
    • GOOGLE_SEARCH_ENGINE_ID: Your Custom Search Engine ID

For Confidential Client (Optional)

  1. Follow steps 1-6 above, but choose Application permissions instead
  2. Certificates & secrets β†’ New client secret β†’ Copy value
  3. Set CLIENT_SECRET and AUTH_MODE=confidential in .env

🚦 Usage

STDIO Transport (MCP Clients)

Windsurf Configuration

{
  "mcpServers": {
    "fx0": {
      "command": "fx0-mcp",
      "env": {
        "TENANT_ID": "your-tenant-id",
        "CLIENT_ID": "your-client-id",
        "SCOPES": "Mail.Read Mail.Send Calendars.ReadWrite Tasks.ReadWrite Chat.ReadWrite Files.ReadWrite offline_access"
      }
    }
  }
}

LM Studio Configuration

{
  "name": "FX0 Server",
  "executable": "fx0-mcp",
  "args": ["--transport", "stdio"],
  "env": {
    "TENANT_ID": "your-tenant-id", 
    "CLIENT_ID": "your-client-id"
  }
}

HTTP/SSE Transport

# Start HTTP server
fx0-mcp --transport http --host 127.0.0.1 --port 8000

# Health check
curl http://localhost:8000/mcp/health

# Initialize MCP session
curl -X POST http://localhost:8000/mcp/initialize \
  -H "Content-Type: application/json" \
  -d '{"protocolVersion": "2024-11-05", "clientInfo": {"name": "test-client", "version": "1.0.0"}}'

# List available tools
curl http://localhost:8000/mcp/tools

# Call a tool
curl -X POST http://localhost:8000/mcp/tools/call \
  -H "Content-Type: application/json" \
  -d '{"name": "m365.mail.list_messages", "arguments": {"folder_id": "inbox", "top": 5}}'

# Connect to Server-Sent Events stream
curl -N -H "Accept: text/event-stream" http://localhost:8000/mcp/sse

# Test with development mode for interactive API docs
fx0-mcp --transport http --dev --no-auth
# Then visit: http://localhost:8000/docs

HTTP API Endpoints

Endpoint Method Description
/mcp/health GET Server health check with tool count
/mcp/initialize POST Initialize MCP protocol session
/mcp/tools GET List all available tools with schemas
/mcp/tools/call POST Execute a specific tool
/mcp/sse GET Server-Sent Events stream for real-time updates
/docs GET Interactive API documentation (dev mode only)

Server-Sent Events

The SSE endpoint provides real-time communication:

// JavaScript example
const eventSource = new EventSource('http://localhost:8000/mcp/sse');

eventSource.onmessage = function(event) {
  const data = JSON.parse(event.data);
  console.log('Received:', data);
  
  if (data.type === 'connected') {
    console.log('Connected with ID:', data.connection_id);
  } else if (data.type === 'heartbeat') {
    console.log('Server heartbeat:', data.server_status);
  }
};

eventSource.onerror = function(error) {
  console.error('SSE error:', error);
};

πŸ”§ Available Tools

Tools follow a hierarchical naming convention: <category>.<domain>.<action>

Tools Description

  • google.tool.search: Search the web for information using Google Custom Search API
  • m365.auth.initiate_login: Start device code sign-in and return instructions
  • m365.auth.poll_login: Wait for device code sign-in to complete
  • m365.auth.status: Check current auth status and identity
  • m365.auth.logout: Clear cached tokens and sign out
  • m365.calendar.create_event: Create a new calendar event
  • m365.calendar.delete_event: Delete a calendar event
  • m365.calendar.find_meeting_times: Find suggested meeting times based on attendee availability
  • m365.calendar.get_event: Get detailed information about a specific calendar event
  • m365.calendar.list_calendars: List all calendars available to the user
  • m365.calendar.list_events: List calendar events within a time range
  • m365.calendar.update_event: Update an existing calendar event
  • m365.mail.create_folder: Create a new email folder
  • m365.mail.delete_message: Delete an email message
  • m365.mail.forward: Forward an email message
  • m365.mail.get_message: Get detailed information about a specific email message
  • m365.mail.list_folders: List email folders
  • m365.mail.list_messages: List email messages from a folder with optional filtering
  • m365.mail.move_message: Move an email message to a different folder
  • m365.mail.reply: Reply to an email message
  • m365.mail.send_email: Send a new email message

Google

Search (fx0.tool.*)

  • google.tool.search(query, num_results?, safe_search?, language?, country?)

MS Graph

Authentication (m365.auth.*)

  1. Initiate login and display to the user:

    • Tool: m365.auth.initiate_login
    • Input (optional): { "scopes": "Mail.Read Mail.Send Calendars.ReadWrite" }
    • Output: verification_uri, user_code, and flow payload
  2. Poll for completion and store token server-side:

    • Tool: m365.auth.poll_login
    • Input: { "flow": <flow from step 1>, "wait": true }
    • Output: status (succeeded|pending|expired) and user identity on success
  3. Check status any time:

    • Tool: m365.auth.status
  4. Logout:

    • Tool: m365.auth.logout

Notes:

  • Device code flow is tenant-aware via TENANT_ID/AUTHORITY.
  • Reserved scopes (openid, profile, offline_access) are filtered automatically for the device flow request.
  • Access tokens are never returned by tools; they are cached and used server-side.

Email (m365.mail.*)

  • m365.mail.list_messages(folder_id?, query?, from_date?, to_date?, top?, skip?)
  • m365.mail.get_message(message_id, include_body?, include_headers?)
  • m365.mail.send_email(to[], subject, body_html|body_text, cc[], bcc[], attachments[])
  • m365.mail.reply(message_id, body, reply_all?) / m365.mail.forward(message_id, to[], body, attachments[])
  • m365.mail.move_message(message_id, destination_folder_id) / m365.mail.delete_message(message_id)
  • m365.mail.create_folder(name, parent_id?) / m365.mail.list_folders(parent_id?)

Calendar (m365.calendar.*)

  • m365.calendar.list_calendars() / m365.calendar.list_events(calendar_id, time_min, time_max, tz, query?)
  • m365.calendar.get_event(event_id) / m365.calendar.create_event(calendar_id, subject, start, end, attendees[], location?, body?)
  • m365.calendar.update_event(event_id, fields) / m365.calendar.delete_event(event_id)
  • m365.calendar.find_meeting_times(attendees[], time_constraints, location?, duration, tz)

To Do (m365.tasks.*) (Future Release)

  • m365.tasks.list_task_lists() / m365.tasks.create_task_list(name) / m365.tasks.delete_task_list(id)
  • m365.tasks.list_tasks(list_id, filter?, order_by?) / m365.tasks.get_task(id)
  • m365.tasks.create_task(list_id, title, due?, importance?, categories[], body?)
  • m365.tasks.update_task(id, fields) / m365.tasks.complete_task(id) / m365.tasks.delete_task(id)

Teams (m365.teams.*) (Future Release)

  • m365.teams.list_teams() / m365.teams.list_channels(team_id) / m365.teams.list_chats()
  • m365.teams.get_channel_messages(team_id, channel_id, top?, cursor?)
  • m365.teams.post_channel_message(team_id, channel_id, body, mentions[])
  • m365.teams.get_chat_messages(chat_id, top?, cursor?) / m365.teams.post_chat_message(chat_id, body, mentions[])
  • m365.teams.create_online_meeting(subject, start, end, attendees[])

SharePoint/OneDrive (m365.files.*) (Future Release)

  • m365.files.list_sites(query?) / m365.files.list_drives(site_id?)
  • m365.files.list_items(drive_id, path?, top?, cursor?)
  • m365.files.get_item(drive_id, item_id) / m365.files.download_item(drive_id, item_id, dest)
  • m365.files.upload_item(drive_id, path, local_file, conflict_behavior=replace|rename)
  • m365.files.create_share_link(drive_id, item_id, type=view|edit, scope=anonymous|organization, expiry?)

Users (m365.users.*) (Future Release)

  • m365.users.get_me() / m365.users.get_user(user_id)
  • m365.users.list_users(query?, top?, skip?)

πŸ§ͺ Development

Setup

git clone https://github.com/your-org/fx0-mcp-server.git
cd fx0-mcp-server

# Create virtual environment
python -m venv venv
source venv/bin/activate  # Linux/Mac
# or: venv\Scripts\activate  # Windows

# Install development dependencies
pip install -e ".[dev]"

# Setup pre-commit hooks
pre-commit install

Testing

# Unit tests
pytest tests/unit

# Integration tests (requires dev tenant)
pytest tests/integration  

# All tests
pytest

# With coverage
pytest --cov=src/fx0_mcp_server --cov-report=html

Code Quality

# Format code
black src/ tests/

# Lint code  
ruff check src/ tests/

# Type checking
mypy src/

πŸ”’ Security

  • Least Privilege: Minimal scopes per domain, delegated permissions preferred
  • Token Security: Encrypted at-rest caching, never logged, optional keyring integration
  • Transport Security: HTTPS required for production HTTP mode, CORS configuration
  • Input Validation: Pydantic schemas, SSRF protection, path traversal guards
  • Audit: Request correlation IDs, sanitized error responses

πŸ“Š Monitoring

  • Health: /mcp/health endpoint with dependency checks
  • Metrics: Optional Prometheus endpoint at /mcp/metrics
  • Logging: Structured JSON logs with correlation IDs
  • Tracing: OpenTelemetry integration for request tracing
  • Alerts: Graph API quota monitoring, authentication failure tracking

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Run quality checks (black, ruff, mypy, pytest)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™‹ Support

πŸ—ΊοΈ Roadmap

  • v0.1.0: STDIO transport, Hierarchical tool taxonomy, Mail + Calendar stub tools (Completed)
  • v0.2.0: Go-Live integration > MS Graph and Google Search Tools, STDIO and HTTP/SSE transport, Docker iamge (Completed)
  • v0.3.0: To Do + Teams tools, advanced search capabilities
  • v0.4.0: SharePoint/OneDrive, file operations
  • v1.0.0: Production hardening, security audit, performance optimization
  • v1.1.0: Webhooks/subscriptions, real-time notifications
  • v1.2.0: Admin tools, compliance helpers, multi-tenant support

Disclaimer: This project is not officially endorsed by Microsoft. Microsoft Graph and related services are trademarks of Microsoft Corporation.

🧰 File Utilities Tools

Six general-purpose tools are available under the fx0.tool.* namespace to export content into files inside the server temp directory (TEMP_DIR, default ./tmp). Each returns a file:// URI and basic metadata:

  • fx0.tool.write_txt (WriteTxtInput β†’ FileCreatedOutput)

    • Inputs: content: str, optional filename, optional subdir
    • Output: { uri, name, mime_type, size_bytes }
  • fx0.tool.write_csv (WriteCsvInput β†’ FileCreatedOutput)

    • Inputs: rows: List[List[Any]] or records: List[Dict], optional headers, optional filename, optional subdir, optional dialect
  • fx0.tool.write_docx (WriteDocxInput β†’ FileCreatedOutput)

    • Requires python-docx
    • Inputs: content: str (newlines become paragraphs), optional filename, optional subdir
  • fx0.tool.write_xlsx (WriteXlsxInput β†’ FileCreatedOutput)

    • Requires openpyxl
    • Inputs: rows or records, optional headers, optional sheet_name, optional filename, optional subdir
  • fx0.tool.write_pdf (WritePdfInput β†’ FileCreatedOutput)

    • Requires reportlab
    • Inputs: content: str, optional filename, optional subdir
  • fx0.tool.write_pptx (WritePptxInput β†’ FileCreatedOutput)

    • Requires python-pptx
    • Inputs: optional title, optional bullets: List[str], optional content: str, optional filename, optional subdir

Notes:

  • When optional libraries are not installed, the tool returns a helpful error message instead of failing.
  • Files are created under TEMP_DIR; you can pass a subdir to organize outputs.

About

MS Graph MCP Server - HTTP/SSE and STDIO also run in Docker

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors