Skip to content

thevysh/githubnotionmcp

Repository files navigation

Notion-GitHub MCP Server

A self-hosted Model Context Protocol (MCP) server that integrates Notion and GitHub APIs with enterprise-grade features including OAuth 2.1 authentication, rate limiting, audit logging, multi-tenant support, and Kubernetes deployment.

Features

  • OAuth 2.1 Authentication: Secure authentication with PKCE flow for GitHub and Notion
  • Rate Limiting: Configurable rate limits per IP and per user (30 requests/min global, 10 writes/min)
  • Audit Logging: Comprehensive logging of all tool invocations with Winston
  • Multi-Tenant Support: Session-based user isolation with secure token storage
  • Health Checks: Kubernetes-ready /healthz and /readyz endpoints
  • Metrics: Prometheus-compatible metrics at /metrics endpoint
  • Docker & Kubernetes: Production-ready containerization and orchestration

Architecture

The server exposes:

  • Tools: Actions that AI models can invoke (create repositories, search Notion, etc.)
  • Resources: Data that AI models can access
  • Authentication: Per-user OAuth tokens ensuring proper authorization

Multi-Tenant Design

Each user's credentials are stored separately, and every request validates the user session before performing operations. This ensures that AI agents never access resources beyond their authorization scope.

Prerequisites

  • Node.js 20+
  • npm or yarn
  • Docker (for containerization)
  • Kubernetes cluster (for production deployment)
  • GitHub OAuth App credentials
  • Notion Integration credentials

Setup

1. Clone and Install

git clone <repository-url>
cd NotionGithubMCP
npm install

2. Configure OAuth Applications

GitHub OAuth App

  1. Go to GitHub Settings > Developer settings > OAuth Apps
  2. Create a new OAuth App
  3. Set Authorization callback URL: http://localhost:8080/auth/github/callback
  4. Copy Client ID and Client Secret

Notion Integration

  1. Go to https://www.notion.so/my-integrations
  2. Create a new integration
  3. Set Redirect URI: http://localhost:8080/auth/notion/callback
  4. Copy OAuth Client ID and Client Secret

3. Environment Variables

Copy .env.example to .env and fill in your credentials:

cp .env.example .env

Edit .env:

PORT=8080
NODE_ENV=development

GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
GITHUB_REDIRECT_URI=http://localhost:8080/auth/github/callback

NOTION_CLIENT_ID=your_notion_client_id
NOTION_CLIENT_SECRET=your_notion_client_secret
NOTION_REDIRECT_URI=http://localhost:8080/auth/notion/callback

SESSION_SECRET=generate_a_random_secret_here

RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=30

LOG_LEVEL=info

4. Build and Run

# Development mode
npm run dev

# Production build
npm run build
npm start

The server will start at http://localhost:8080

Usage

Authentication Flow

  1. Visit http://localhost:8080/dashboard
  2. Click "Connect GitHub" or "Connect Notion"
  3. Authorize the application
  4. You'll be redirected back with authentication confirmed

Available Endpoints

Authentication

  • GET /auth/github - Initiate GitHub OAuth flow
  • GET /auth/github/callback - GitHub OAuth callback
  • GET /auth/notion - Initiate Notion OAuth flow
  • GET /auth/notion/callback - Notion OAuth callback
  • GET /auth/status - Check authentication status
  • POST /auth/logout - Logout

GitHub Tools

  • POST /tools/github/repositories - List repositories
  • POST /tools/github/create-repository - Create new repository
  • POST /tools/github/repository - Get repository details
  • POST /tools/github/create-issue - Create issue
  • POST /tools/github/issues - List issues

Notion Tools

  • POST /tools/notion/search - Search Notion
  • POST /tools/notion/create-page - Create page
  • POST /tools/notion/page - Get page details
  • POST /tools/notion/update-page - Update page
  • POST /tools/notion/databases - List databases
  • POST /tools/notion/query-database - Query database

Monitoring

  • GET /healthz - Health check
  • GET /readyz - Readiness check
  • GET /metrics - Prometheus metrics

Docker Deployment

Build Docker Image

docker build -t notion-github-mcp:latest .

Run with Docker Compose

docker-compose up -d

This starts:

  • MCP Server on port 8080
  • Prometheus on port 9090
  • Grafana on port 3000

Kubernetes Deployment

1. Create Secrets

kubectl create secret generic oauth-secrets \
  --from-literal=github-client-id=YOUR_GITHUB_CLIENT_ID \
  --from-literal=github-client-secret=YOUR_GITHUB_CLIENT_SECRET \
  --from-literal=notion-client-id=YOUR_NOTION_CLIENT_ID \
  --from-literal=notion-client-secret=YOUR_NOTION_CLIENT_SECRET \
  --from-literal=session-secret=YOUR_RANDOM_SESSION_SECRET

2. Update ConfigMap

Edit k8s/configmap.yaml with your domain:

data:
  github-redirect-uri: "https://your-domain.com/auth/github/callback"
  notion-redirect-uri: "https://your-domain.com/auth/notion/callback"

3. Update Ingress

Edit k8s/ingress.yaml with your domain:

spec:
  tls:
  - hosts:
    - your-domain.com

4. Deploy

kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml
kubectl apply -f k8s/network-policy.yaml

5. Verify Deployment

kubectl get pods
kubectl get services
kubectl get ingress
kubectl logs -f deployment/mcp-server

MCP Server (stdio mode)

To run as an MCP server using stdio transport:

MCP_MODE=stdio npm start

This mode is designed to be used with MCP clients that communicate via standard input/output.

Monitoring

Prometheus Metrics

Available metrics:

  • http_requests_total - Total HTTP requests
  • http_request_duration_seconds - Request duration histogram
  • tool_calls_total - Total tool invocations
  • tool_call_duration_seconds - Tool call duration histogram
  • rate_limit_hits_total - Rate limit violations

Grafana Dashboards

Access Grafana at http://localhost:3000:

  • Default credentials: admin/admin
  • Add Prometheus datasource: http://prometheus:9090
  • Create dashboards for metrics visualization

Audit Logs

All tool invocations are logged to:

  • Console (formatted)
  • logs/combined.log (all logs)
  • logs/error.log (errors only)

Log format:

{
  "timestamp": "2025-10-24T10:00:00Z",
  "user": "user@example.com",
  "action": "github.create_repository",
  "params": {"name": "my-repo"},
  "result": "success"
}

Security Considerations

  1. Never commit secrets: Use environment variables or Kubernetes secrets
  2. Enable HTTPS: Always use TLS in production
  3. Rotate secrets: Regularly rotate OAuth secrets and session keys
  4. Rate limiting: Adjust limits based on your use case
  5. Network policies: Restrict egress to required services only
  6. Token storage: Use encrypted database in production (not in-memory)

Rate Limiting

  • Global: 30 requests/min per IP
  • Per-user: 30 requests/min per authenticated user
  • Write operations: 10 requests/min per user

Adjust in .env:

RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=30

Troubleshooting

Authentication fails

  • Verify OAuth credentials are correct
  • Check redirect URIs match exactly
  • Ensure callbacks are reachable

Rate limiting too strict

  • Adjust RATE_LIMIT_MAX_REQUESTS in environment
  • Consider per-endpoint limits for your use case

Kubernetes pods not starting

  • Check secrets are created: kubectl get secrets
  • View logs: kubectl logs deployment/mcp-server
  • Verify resource limits are adequate

Development

Project Structure

.
├── src/
│   ├── auth/           # OAuth implementation
│   ├── middleware/     # Rate limiting, metrics
│   ├── mcp/            # MCP server implementation
│   ├── routes/         # Express routes
│   ├── services/       # GitHub and Notion services
│   ├── types/          # TypeScript types
│   ├── utils/          # Logger and utilities
│   └── index.ts        # Main application
├── k8s/                # Kubernetes manifests
├── logs/               # Log files
├── Dockerfile          # Docker configuration
├── docker-compose.yml  # Docker Compose setup
└── package.json        # Dependencies

Adding New Tools

  1. Add service method in src/services/github.ts or src/services/notion.ts
  2. Register tool in src/mcp/server.ts (ListToolsRequestSchema handler)
  3. Implement handler in src/mcp/server.ts (CallToolRequestSchema handler)
  4. Add Express route in src/routes/tools.ts

License

MIT

Contributing

Contributions welcome! Please open an issue or submit a pull request.

Support

For issues and questions, please open a GitHub issue.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published