mcp-server

topautoadvisorsg-prog/mcp-server

3.1

If you are the rightful owner of mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.

The mcp-server is a robust Express.js REST API designed to integrate ChatGPT with Google Workspace and HubSpot CRM.

MCP Server

Overview

The mcp-server project is a production-ready Express.js REST API that lets ChatGPT (via MCP Actions) orchestrate work across Google Workspace (Docs, Sheets, Calendar, Drive) and HubSpot CRM (Contacts, Companies, Deals). It exposes JSON-first endpoints secured with a shared MCP API key, includes structured logging and rate limiting, and is deployable to Vercel on Node.js 20.x.

Architecture

mcp-server/
├── index.js                # Express bootstrap, middleware, router wiring
├── api/index.js            # Vercel entry point re-exporting the Express app
├── routes/
│   ├── google/
│   │   ├── docs.js
│   │   ├── sheets.js
│   │   ├── calendar.js
│   │   └── drive.js
│   └── hubspot/
│       ├── contacts.js
│       ├── companies.js
│       └── deals.js
├── auth/
│   ├── google.js           # OAuth2 client factory for Google APIs
│   └── hubspot.js          # HubSpot authorization helpers
├── services/
│   ├── googleClient.js     # Google Workspace service layer
│   └── hubspotClient.js    # HubSpot CRM service layer
├── middleware/
│   ├── authMiddleware.js   # MCP API key validation
│   ├── errorHandler.js     # Centralized error response shaping
│   └── rateLimiter.js      # Global rate limiter
├── utils/
│   ├── asyncHandler.js     # Promise wrapper for Express handlers
│   ├── logger.js           # Pino logger configuration
│   └── retry.js            # Exponential backoff helper
├── vercel.json             # Deployment configuration targeting Node 20.x
├── public/
│   ├── favicon.ico
│   └── openapi.yaml        # ChatGPT Actions compliant contract served statically
├── .env.example            # Environment variable template
├── package.json
└── README.md

Runtime Requirements

  • Node.js 20.x (enforced via engines field and vercel.json)
  • npm or pnpm for dependency management

Deployment (Vercel)

  1. Connect this GitHub repository to Vercel.
  2. Vercel detects vercel.json and deploys api/index.js as a serverless function on Node.js 20.x.
  3. Configure the environment variables (see below) in the Vercel Project → Settings → Environment Variables.
  4. Each push to main (or your chosen branch) triggers an automatic deployment. Promote to production once verified.

Environment Variables

Populate these in .env for local development and configure them in Vercel Project → Settings → Environment Variables before deploying. Never commit real secret values to the repository:

NameDescription
GOOGLE_CLIENT_IDGoogle OAuth client ID with Docs, Sheets, Drive, and Calendar scopes.
GOOGLE_CLIENT_SECRETGoogle OAuth client secret.
GOOGLE_REFRESH_TOKENRefresh token authorized for the required Google scopes.
HUBSPOT_PRIVATE_APP_TOKENHubSpot private app access token (or OAuth access token).
HUBSPOT_CLIENT_ID(Optional) HubSpot OAuth client ID for future enhancements.
HUBSPOT_CLIENT_SECRET(Optional) HubSpot OAuth client secret for future enhancements.
HUBSPOT_BASE_URL(Optional) Override for HubSpot API base URL (defaults to https://api.hubspot.com).
MCP_API_KEYShared secret for all API calls. Configure as a secure random string in your environment.
LOG_LEVEL(Optional) Pino log level (info, debug, etc.).
RATE_LIMIT_MAX_REQUESTS(Optional) Override of per-minute request ceiling.
PORT(Optional) Local development port, defaults to 3000.

Local Development & Testing

  1. Install dependencies:
    npm install
    
  2. Copy the environment template and fill in secrets:
    cp .env.example .env
    
  3. Start the server:
    npm run dev
    
  4. Confirm the server is healthy:
    curl http://localhost:3000/health
    
  5. Call endpoints with the Authorization: Bearer <MCP_API_KEY> header. Example cURL:
    curl -X POST http://localhost:3000/google/docs/create \
      -H 'Content-Type: application/json' \
      -H 'Authorization: Bearer <YOUR_MCP_API_KEY>' \
      -d '{
        "title": "MCP Demo Doc",
        "body": "Hello from ChatGPT"
      }'
    
  6. For Drive uploads, send base64 content:
    curl -X POST http://localhost:3000/google/drive/upload \
      -H 'Content-Type: application/json' \
      -H 'Authorization: Bearer <YOUR_MCP_API_KEY>' \
      -d '{
        "name": "hello.txt",
        "mimeType": "text/plain",
        "content": "SGVsbG8gV29ybGQh"
      }'
    

Registering with ChatGPT Actions

  1. Deploy the server and confirm the base URL (https://mcp-server-lilac.vercel.app by default).
  2. In ChatGPT → Settings → Actions → Add new action, supply the public openapi.yaml URL: https://mcp-server-lilac.vercel.app/openapi.yaml.
  3. Under Authentication, choose Bearer Token and set the value to your MCP_API_KEY.
  4. Save; ChatGPT will validate the schema and begin using the actions.

Troubleshooting

  • Node version errors: Ensure Vercel project is set to Node 20.x (see Project Settings) and that your local environment matches.
  • Favicon not found on Vercel: Confirm vercel.json route /favicon.ico points to /public/favicon.ico and that the file exists.
  • 401 Unauthorized: Verify the Authorization: Bearer <MCP_API_KEY> header and that the environment variable matches exactly in Vercel/local .env.
  • Google 403 / scope issues: Check that the refresh token was generated with Docs, Sheets, Drive, and Calendar scopes. Regenerate the OAuth consent if scopes changed.
  • HubSpot 401/403: Confirm the private app token has CRM scope permissions and hasn’t been rotated.
  • HTTP 429 / quota limits: The retry helper automatically backs off on 429s, but persistent rate limiting requires increasing quotas or pacing requests.
  • Server cold start latency: First request to the Vercel serverless function may take a few seconds. Warm the endpoint before mission-critical workflows.

Security Notes

  • All routes enforce the MCP API key via middleware.
  • Sensitive credentials are never logged; Pino redacts authorization headers.
  • Only JSON payloads are accepted, and uploads require base64 encoding to avoid multipart/form-data.
  • No sample API keys are stored in the repository—always inject secrets via environment variables.

Testing Checklist

  • npm run dev – start Express in watch mode.
  • npm run lint – run ESLint (configure Node/npm auth if necessary before running).