MCP Server Railway Starter
A starter template for deploying a remote MCP server with OAuth 2.1 authorization, dynamic client registration, and a PostgreSQL database. Includes example tools for notes and whoami.
README
Remote MCP server starter for Railway
A Model Context Protocol server your agent connects to over the network, with a working OAuth 2.1 authorization server in front of it. Deploy it, add the URL to your client, type a password once — the client registers itself and gets a token.
Why this exists
The catalogue has plenty of MCP servers, and almost all of them wrap somebody else's SaaS: a server for Whoop, one for Meta Ads, one for a CRM. If what you want is to expose your own data — an internal API, a database, a document store — there is nothing to start from.
The hard part was never the tools. It is everything around them:
- Transport. Streamable HTTP replaced SSE, and stateless is the shape that survives more than one replica. Sessions in memory mean sticky routing.
- Authorization. The MCP spec puts OAuth 2.1 in the required path: PKCE, dynamic client registration, protected-resource metadata under RFC 9728, resource indicators under RFC 8707. Clients will not connect without it.
- Storage. Codes and tokens have to outlive the process that issued them, or every deploy logs everyone out and a second replica rejects the first one's tokens.
This starter does all three, and leaves you three example tools to replace.
What you get
| Path | What it is |
|---|---|
/mcp |
The MCP endpoint. Streamable HTTP, stateless, bearer-protected |
/.well-known/oauth-protected-resource |
RFC 9728 metadata, so clients can find the authorization server |
/.well-known/oauth-authorization-server |
RFC 8414 metadata: endpoints, PKCE method, scopes |
/register |
Dynamic client registration (RFC 7591) — no pre-shared credentials |
/authorize, /token, /revoke |
The authorization code flow with PKCE, plus refresh and revocation |
/login |
The one human step: your password, once per client |
/health |
Checks Postgres, so a broken database shows up as unhealthy |
Three example tools — add_note, search_notes, whoami — are backed by a real
table. They exist so a fresh deployment can be proven end to end, and so you have
a working handler to copy.
Deploy
Two services: this repository and a Postgres. The template wires them together and generates the password for you.
After the first deploy, open the service URL — the page shows the exact URL to paste into your client.
Add it to a client
Use https://<your-domain>/mcp. The client discovers the authorization server,
registers itself, opens the login page in a browser, and stores the token it
gets back. There is nothing to configure on the client side and no API key to
copy around.
For clients that speak stdio only, npx mcp-remote https://<your-domain>/mcp
bridges the two.
Prove it works
npx tsx scripts/verify-oauth-flow.ts https://<your-domain> '<the password>'
The script walks the whole path a real client walks — discovery, registration,
PKCE, login, token exchange, tools/call — and also checks the parts that are
supposed to fail: an unauthenticated call, a wrong password, a replayed
authorization code.
Write your own tools
src/tools.ts is the whole surface. Add a registerTool call with a Zod input
schema and a handler; the token that authorized the call arrives as auth, so
you can key data by auth.clientId or check auth.scopes per tool.
The example tools are deliberately backed by Postgres rather than returning canned strings — that is what makes a first deploy prove the write path.
How the security is set up
- Tokens are stored hashed (SHA-256). A database dump does not hand anyone a working token.
- Authorization codes are single-use, enforced by marking them consumed in the same statement that reads them, so a replay finds nothing to update — not by a check-then-write that two concurrent requests can both pass.
- PKCE is required (S256); the code challenge is bound to the code.
- Login is rate limited — 10 attempts per address per 15 minutes, counted in Postgres so the limit holds across replicas rather than per process.
- Passwords are compared in constant time, over hashes, so neither content nor length leaks through timing.
- Refresh rotates: using a refresh token revokes it and issues a new pair. A refresh can narrow its scopes, never widen them.
One honest note: client secrets issued by dynamic registration are stored as issued, because the SDK's client authentication compares them directly. MCP clients normally register as public clients and rely on PKCE, which is the path this server expects.
Configuration
| Variable | Required | Purpose |
|---|---|---|
DATABASE_URL |
yes | Postgres for clients, codes, tokens |
MCP_ADMIN_PASSWORD |
yes | The password on the login page; at least 12 characters |
PUBLIC_URL |
on Railway, filled in | The origin clients reach — becomes the OAuth issuer |
PORT |
no | Defaults to 8080 |
MCP_SERVER_NAME |
no | Name reported to clients |
ACCESS_TOKEN_TTL_SECONDS |
no | Default 3600 |
REFRESH_TOKEN_TTL_SECONDS |
no | Default 2592000 (30 days) |
Run locally
npm ci
cp .env.example .env
npm run dev
The SDK refuses a plain-HTTP issuer except on localhost, which is exactly where you will be running it.
Using an external identity provider
This server is its own authorization server, which is what makes it deploy in
one click. If you already run Keycloak, Auth0 or Zitadel, replace mcpAuthRouter
with mcpAuthMetadataRouter and point it at your issuer; the tools and transport
stay as they are.
A note on versions
Built on @modelcontextprotocol/sdk 1.29.0, the current stable line. The v2 SDK
splits into @modelcontextprotocol/server and friends and is still in beta at
the time of writing; this starter will move when it stabilises.
License
MIT
推荐服务器
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 模型以安全和受控的方式获取实时的网络信息。