about-utkarsh-mcp
An MCP (Model Context Protocol) server that exposes information about Utkarsh —bio, skills, work experience, and portfolio projects — to any MCP-compatible client(Claude, Claude Code, ChatGPT, Codex, etc.).
It ships two transports from one shared server implementation:
| Transport | File | Used by |
|---|---|---|
| stdio | src/transports/stdio.ts |
Local clients that launch the server as a subprocess: Claude Desktop, Claude Code, Codex CLI |
| Streamable HTTP (remote) | src/transports/http.ts |
Remote clients that connect over a URL: ChatGPT connectors, remote Claude/Claude Code, any HTTP-based MCP client |
The remote HTTP transport is protected with OAuth 2.0, including Dynamic ClientRegistration (DCR, RFC 7591) — so a new MCP client can self-register and connectwithout any manual "create an API key" step, exactly as the MCP Authorization specexpects for remote servers.
Architecture
src/
data/profile.ts # Single source of truth: bio, skills, experience, projects
mcpServer.ts # Shared MCP server: tools + one resource, used by both transports
transports/
stdio.ts # Local subprocess transport
http.ts # Remote Streamable HTTP transport (OAuth-protected)
oauth/
store.ts # In-memory client/auth-code store
router.ts # DCR, authorize (PKCE), token, discovery metadata endpoints
MCP tools exposed
get_bio— name, title, location, experience summary, linksget_skills— skills by category (languages/frontend/backend/databases/infra/spoken)get_experience— work historylist_projects— all portfolio projects (summary)get_project_details— full detail for one named projectget_contact— how to reach out
Plus one resource: profile://utkarsh/full (the whole profile as JSON).
OAuth / DCR flow (remote HTTP transport)
- Client discovers the server via
GET /.well-known/oauth-protected-resource(RFC 9728) andGET /.well-known/oauth-authorization-server(RFC 8414). - Client dynamically registers itself:
POST /register(RFC 7591) — nopre-shared client id/secret needed. - Client runs the standard Authorization Code + PKCE flow:
GET /authorize(a one-click "Approve" page — there's no personal login here, just consentto read a public profile) →POST /token. - Client calls
POST/GET/DELETE /mcpwithAuthorization: Bearer <token>.
This was verified end-to-end (registration → authorize → token exchange →authenticated initialize and tools/call) during development.
Local development
npm install
npm run build
# Local/stdio mode (what Claude Desktop / Claude Code / Codex CLI use)
npm run start:stdio
# Remote/HTTP mode (what ChatGPT / remote clients use)
npm run start:http
# or, to test without OAuth while developing:
REQUIRE_AUTH=false npm run start:http
Deployment (remote HTTP server)
The included Dockerfile builds a production image; render.yaml is a one-clickblueprint for Render, but this deploys the same way onRailway, Fly.io, or any container host.
Render (recommended, free tier available)
- Push this repo to GitHub.
- On Render: New → Blueprint, point it at the repo —
render.yamlconfigureseverything (including generating a randomJWT_SECRET). - Once deployed, set
PUBLIC_BASE_URLto the assignedhttps://<app>.onrender.comURL in the service's environment settings and redeploy, so OAuth metadataadvertises the correct absolute URLs. - Your MCP endpoint is
https://<app>.onrender.com/mcp.
Any other Docker host (Railway, Fly.io, a VPS, etc.)
docker build -t about-utkarsh-mcp .
docker run -p 3000:3000 \
-e JWT_SECRET=$(node -e "console.log(require('crypto').randomBytes(48).toString('hex'))") \
-e PUBLIC_BASE_URL=https://your-deployed-domain.example.com \
about-utkarsh-mcp
Connecting clients
Claude Desktop / Claude Code (local, stdio)
Add to your MCP config (Claude Desktop: claude_desktop_config.json; Claude Code:.mcp.json or claude mcp add):
{
"mcpServers": {
"about-utkarsh": {
"command": "node",
"args": ["/absolute/path/to/about-utkarsh-mcp/dist/transports/stdio.js"]
}
}
}
Or with Claude Code's CLI:
claude mcp add about-utkarsh -- node /absolute/path/to/dist/transports/stdio.js
Claude (remote, HTTP + OAuth)
In Claude's connector/MCP settings, add a remote MCP server and give it thedeployed URL's /mcp endpoint, e.g.:
https://about-utkarsh-mcp.onrender.com/mcp
Claude will auto-discover the OAuth metadata, register itself via DCR, and walkyou through the one-click approval — no manual credentials required.
ChatGPT (connectors / remote MCP)
In ChatGPT's connector settings, add a custom connector pointing at the samehttps://about-utkarsh-mcp.onrender.com/mcp URL. ChatGPT performs the samediscovery → DCR → OAuth flow described above.
Codex
- Codex CLI (local): configure it the same way as Claude Code above — pointit at
node dist/transports/stdio.js. - Codex web/cloud (remote): use the deployed
/mcpURL the same way as theChatGPT connector above.
Notes on the OAuth implementation
- Storage for registered clients/auth codes is in-memory (
src/oauth/store.ts)— fine for an assessment/demo; swap in a real database for production soregistrations survive restarts and multiple instances. - Access tokens are short-lived HS256 JWTs (1 hour). There's no user login screenbecause the "resource" being protected is a public profile with no per-userdata — the approval screen exists to satisfy the OAuth consent step the MCPspec expects, not to gate a private account.
- PKCE (RFC 7636) is enforced for public clients (
token_endpoint_auth_method: none),which is what DCR-registered MCP clients typically use.
Keeping the data current
Everything the tools return lives in src/data/profile.ts. Update that file andredeploy to change what the server tells clients about Utkarsh.