A minimal, production-ready MCP server template built with TypeScript. Clone this, replace the example tools with your API, and your users can interact with your product through Claude, Cursor, or any MCP-compatible AI agent.
Built lean by design — exposes only what users need, with token-efficient tool descriptions and structured responses.
# Clone
git clone https://github.com/SoftwareSavants/mcp-starter.git
cd mcp-starter
# Install
npm install
# Configure (pre-filled with DummyJSON — works out of the box)
cp .env.example .env
# Build & run
npm run build
npm startThen add to your Claude Desktop config (~/Library/Application\ Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"my-product": {
"command": "node",
"args": [
"--env-file=path/to/mcp-starter/.env",
"path/to/mcp-starter/dist/index.js"
]
}
}
}This template supports two transport modes. Use whichever fits your deployment:
| Stdio (default) | HTTP + OAuth | |
|---|---|---|
| Auth | API key via env var | OAuth 2.1 (PKCE) |
| Best for | Local dev, Claude Desktop | Production, multi-user, remote |
| Run | npm start |
npm run start:http |
The default. Set API_BASE_URL and API_KEY as environment variables — the server authenticates all API calls with the key.
Runs an Express server with full OAuth 2.1 support. The MCP server acts as a proxy — it delegates authentication to your upstream OAuth provider (e.g. your product's existing OAuth server).
# Required environment variables for OAuth mode
export API_BASE_URL="https://api.yourproduct.com"
export OAUTH_AUTHORIZATION_URL="https://auth.yourproduct.com/authorize"
export OAUTH_TOKEN_URL="https://auth.yourproduct.com/token"
export OAUTH_USERINFO_URL="https://api.yourproduct.com/userinfo"
export OAUTH_CLIENT_ID="your-oauth-client-id"
export OAUTH_CLIENT_SECRET="your-oauth-client-secret"
export OAUTH_SCOPES="read,write" # comma-separated
export OAUTH_ISSUER_URL="https://mcp.yourproduct.com" # optional, defaults to http://localhost:3000
export PORT=3000 # optional
npm run start:httpClaude Desktop config for HTTP mode:
{
"mcpServers": {
"my-product": {
"url": "https://mcp.yourproduct.com/mcp"
}
}
}How it works:
- Client connects to
/mcpand gets redirected to your OAuth provider - User authorizes the MCP client with your service
- Client receives an access token and sends it with each MCP request
- The server verifies the token and uses it to call your API on behalf of the user
src/index.ts— Server entry point, registers tools, picks transport modesrc/tools/— Example tools (list, get, create, search) you replace with your APIsrc/auth.ts— API key and OAuth token authenticationsrc/types.ts— Shared typessrc/transports/stdio.ts— Stdio transport (default)src/transports/http.ts— HTTP transport with OAuth middlewaresrc/oauth-provider.ts— Proxy OAuth provider config- Built-in error handling with user-friendly messages
- Token-efficient tool descriptions (lean, not bloated)
Edit src/tools/ — each file exports one tool. A tool has:
export const listItems: Tool = {
name: "list_items",
description:
"List items with optional filters. Returns name, ID, and status.", // Keep it SHORT
inputSchema: {
type: "object",
properties: {
status: {
type: "string",
enum: ["active", "archived"],
description: "Filter by status",
},
limit: { type: "number", description: "Max results (default 10)" },
},
},
handler: async (args) => {
const data = await api.get("/items", { params: args });
// Return ONLY what the agent needs — not the full API response
return data.items.map((i) => ({
id: i.id,
name: i.name,
status: i.status,
}));
},
};Update src/auth.ts with your authentication method and API_BASE_URL in env.
Update src/oauth-provider.ts with your token verification logic. The default uses a userinfo endpoint — adapt it to however your service validates tokens (JWT verification, introspection endpoint, etc.).
- 5-10 tools max. Only expose what users actually do through AI.
- Short descriptions. One sentence. The LLM reads every tool description on every request.
- Structured responses. Return
{ id, name, status }not the full database row. - No nested JSON blobs. Flatten where possible.
This template follows the "Built Lean" philosophy:
- Minimal tool surface — fewer tools = agent picks the right one every time
- Token-efficient descriptions — every character in a tool description costs tokens on every request
- Structured responses — clean returns that keep the context window lean
- Fail gracefully — clear error messages the agent can relay to the user
This template gets you started. For a production-grade MCP server with auth, permissions, documentation, and ongoing maintenance — talk to us.
Software Savants — the AI-native product studio. We build lean MCP servers that don't bloat the context window.
MIT