MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Servercalculate 15 * 7"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Server
Node.js + Express MCP server for ChatGPT with:
OAuth 2.0 Authorization Code Flow + PKCE
S256refresh token rotation
Supabase Postgres persistence
MCP Streamable HTTP endpoint at
/mcpsample tools:
calculator,get_weather,search_webcleanup 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 .envEdit .env:
BASE_URLDATABASE_URLCORS_ORIGINSMCP_ALLOWED_ORIGINSMCP_ALLOWED_HOSTSENABLE_CLEANUP_JOBCLEANUP_INTERVAL_MINUTESAUTO_SEED_*
Check database connectivity:
npm run db:check
npm run db:initRun locally:
npm run devHealth check:
GET http://localhost:3000/healthzRun cleanup manually:
npm run cleanup:run3. Expose with ngrok
ngrok http 3000Take the HTTPS URL from ngrok and set it as:
BASE_URLadd the ngrok origin to
MCP_ALLOWED_ORIGINSadd the ngrok host to
MCP_ALLOWED_HOSTSone of the registered redirect URIs in
oauth_clients
Restart the server after updating .env.
4. OAuth endpoints
Authorization endpoint
GET /authorizePOST /authorize/decisiondemo consent screen with optional auto-approve mode
validates:
client_idredirect_uriresponse_type=codecode_challengecode_challenge_method=S256scopes
Token endpoint
POST /tokensupports:
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 markedcompromisedsession 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
/mcpbearer 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 return405this 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/authorizeToken URL:
https://your-domain/tokenRevoke URL:
https://your-domain/revokeMCP 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_clientsstore 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,/revokeOAuth 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
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/buitanphat247/mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server