MCP Server
Node.js MCP server for ChatGPT with OAuth 2.0 authorization code flow + PKCE, refresh token rotation, and Supabase-backed persistence. Includes sample tools like calculator, get_weather, and search_web.
README
MCP Server
Node.js + Express MCP server for ChatGPT with:
- OAuth 2.0 Authorization Code Flow + PKCE
S256 - refresh token rotation
- Supabase Postgres persistence
- MCP Streamable HTTP endpoint at
/mcp - sample tools:
calculator,get_weather,search_web - cleanup job for expired OAuth records
Structure
mcp-server/
|-- .env.example
|-- IMPLEMENTATION_REPORT.md
|-- package.json
|-- README.md
|-- supabase/
| `-- schema.sql
`-- src/
|-- app.js
|-- server.js
|-- config/
|-- mcp/
|-- middleware/
|-- routes/
|-- scripts/
|-- services/
|-- tools/
`-- utils/
1. Supabase setup
- Create a Supabase project.
- Open the SQL editor.
- Run
supabase/schema.sql. - Copy the Postgres connection string into
.envasDATABASE_URL.
For IPv4-only networks, use the Supabase Session Pooler URI instead of the direct IPv6 connection string.
Seed an OAuth client
You need at least one record in oauth_clients.
For local development the server can seed one automatically from env:
AUTO_SEED_CLIENT_IDAUTO_SEED_CLIENT_NAMEAUTO_SEED_CLIENT_SECRETAUTO_SEED_REDIRECT_URIS
If AUTO_SEED_CLIENT_SECRET is empty, the client is treated as public and may use none auth at the token endpoint.
If it is set, the client supports both client_secret_basic and client_secret_post.
2. Local setup
cd mcp-server
npm install
copy .env.example .env
Edit .env:
BASE_URLDATABASE_URLCORS_ORIGINSMCP_ALLOWED_ORIGINSMCP_ALLOWED_HOSTSENABLE_CLEANUP_JOBCLEANUP_INTERVAL_MINUTESAUTO_SEED_*
Check database connectivity:
npm run db:check
npm run db:init
Run locally:
npm run dev
Health check:
GET http://localhost:3000/healthz
Run cleanup manually:
npm run cleanup:run
3. Expose with ngrok
ngrok http 3000
Take the HTTPS URL from ngrok and set it as:
BASE_URL- add the ngrok origin to
MCP_ALLOWED_ORIGINS - add the ngrok host to
MCP_ALLOWED_HOSTS - one of the registered redirect URIs in
oauth_clients
Restart the server after updating .env.
4. OAuth endpoints
Authorization endpoint
GET /authorizePOST /authorize/decision- demo consent screen with optional auto-approve mode
- validates:
client_idredirect_uriresponse_type=codecode_challengecode_challenge_method=S256- scopes
Token endpoint
POST /token- supports:
grant_type=authorization_codegrant_type=refresh_token
Client authentication:
noneclient_secret_basicclient_secret_post
Discovery
GET /.well-known/oauth-authorization-serverGET /.well-known/openid-configuration
Revoke
POST /revoke
5. Refresh token rotation
This server rotates refresh tokens on every refresh request:
- the current refresh token row is locked
- the old refresh token is revoked
- a new access token is issued
- a new refresh token is issued
- rotation lineage is stored in Postgres
If a revoked or replaced refresh token is reused:
- the backing
mcp_sessionis markedcompromised - session tokens are revoked
- the request fails with
invalid_grant
6. MCP endpoint
Main MCP endpoint:
POST /mcp
Behavior:
- uses MCP Streamable HTTP transport
- path is
/mcp - bearer access token is required
- host and origin allowlists are enforced
- the implementation is stateless on the transport layer
- each HTTP request creates a fresh MCP server and transport instance
- no in-memory MCP transport session map is retained across requests or restarts
Compatibility note:
GET /mcpandDELETE /mcpcurrently return405- this server is using the stateless streamable HTTP pattern, not SSE session transport
7. Sample tools
calculatorget_weathersearch_web
These are in src/tools/ and registered via src/mcp/tool-registry.js.
8. Cleanup job
The server starts a background cleanup job on boot when ENABLE_CLEANUP_JOB=true.
It removes:
- expired or stale authorization codes
- expired or revoked access tokens older than 1 day
- expired or revoked refresh tokens older than 7 days
Interval is controlled by CLEANUP_INTERVAL_MINUTES.
9. Register in ChatGPT
Use your deployed server values:
- Authorization URL:
https://your-domain/authorize - Token URL:
https://your-domain/token - Revoke URL:
https://your-domain/revoke - MCP URL:
https://your-domain/mcp
Recommended scopes:
mcp.tools.calloffline_access
PKCE:
- required
- method:
S256
If ChatGPT or your connector uses a confidential client:
- create the client in
oauth_clients - store the secret hash
- allow
client_secret_basicand/orclient_secret_post
10. Security notes
- token values are stored hashed in Postgres
- client secrets are stored hashed
- rate limiting is applied to
/authorize,/token,/revoke - OAuth errors use standard fields:
errorerror_description
- raw secrets and tokens are not logged
- refresh token reuse triggers session compromise handling
11. Current status
Verified against real Supabase:
npm run db:checknpm run db:initnpm run cleanup:run
What is still intentionally basic:
- the consent page is a demo flow, not a real user login system
- access tokens are opaque and require a DB lookup
- there is no automated test suite yet
- rate limits and allowlists should be tightened before production
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。