Sewa Setu — Old Age Pension Portal

Department of Social Welfare · Government of Purvanchal

Seva Setu documentation

The Old Age Pension portal is the system of record. Two MCP servers over streamable HTTP let AI assistants apply or follow up as a citizen, or review and decide as a block officer. MCP tools call the same validation and write paths as the web forms. Agents cannot invent eligibility the portal would refuse.

Live URLs Admin login Citizen portal Officer dashboard MCP install Eval dashboard Local compose Design ยท MCP detail

Live URLs

SurfaceURL
Portalhttps://seva-setu.ruchir.dev
Docshttps://seva-setu.ruchir.dev/docs/
Eval dashboardhttps://seva-setu.ruchir.dev/eval-dashboard
Citizen MCPhttps://seva-setu.ruchir.dev/mcp/citizen
Officer MCPhttps://seva-setu.ruchir.dev/mcp/officer
SMS OTP inbox/__gateway/

Admin login

For officer web flows and OAuth with scope=officer:

Sign in at /admin.

Citizen portal

  1. Open /apply, enter a 10-digit mobile, solve the captcha, request an OTP.
  2. Read the OTP from /__gateway/ or /__gateway/api/messages?to=<mobile>.
  3. Complete the form steps: personal details, address, bank account and IFSC.
  4. Upload age proof as JPG, PNG, or PDF up to 5 MB.
  5. Submit the declaration. Note the application number.

Track or withdraw a pending application at /status. The password is the date of birth as DDMMYYYY. One active application is allowed at a time. Statuses PENDING, APPROVED, and DEEMED_APPROVED block a new apply until withdraw or a terminal reject.

Agent apply through the citizen MCP is limited to blocks Sonari, Rajapara, and Namti. Other blocks must use the portal or a CSC.

Officer dashboard

  1. Sign in at /admin with the admin credentials above.
  2. The dashboard shows counts by status, overdue PENDING cases past the 15-day SLA, and pending volume by block.
  3. Open Pending to review a case. Approve or reject with a reason recorded under the signed-in officer name.
  4. Optional: mint a long-lived program token at /admin/tokens for unattended officer MCP use. The token audience must be the officer MCP URL.

MCP install

Full MCP notes: /docs/mcp.

Short version:

Opening an MCP URL in a browser with GET returns 401. That is expected. The endpoint needs a Bearer token and an MCP client using streamable HTTP, not a plain page load.

Claude Code / Cursor config

{
  "mcpServers": {
    "seva-setu-citizen": {
      "type": "http",
      "url": "https://seva-setu.ruchir.dev/mcp/citizen"
    },
    "seva-setu-officer": {
      "type": "http",
      "url": "https://seva-setu.ruchir.dev/mcp/officer"
    }
  }
}

Claude Code also accepts:

claude mcp add --transport http seva-setu-citizen \
  https://seva-setu.ruchir.dev/mcp/citizen
claude mcp add --transport http seva-setu-officer \
  https://seva-setu.ruchir.dev/mcp/officer

Cursor: put the same JSON in ~/.cursor/mcp.json or .cursor/mcp.json. A remote entry with only url is enough for OAuth discovery in the IDE.

Eval dashboard

Live results: /eval-dashboard.

Personas in evals/personas.json run against the real MCP servers with real OAuth and Postgres assertions. The runner writes evals/results/latest.json, which the portal renders.

ADMIN_PASSWORD='CAz4uecdpQIfoi2o2AM7xaza' \
PUBLIC_BASE_URL='https://seva-setu.ruchir.dev' \
CITIZEN_MCP_URL='https://seva-setu.ruchir.dev/mcp/citizen' \
OFFICER_MCP_URL='https://seva-setu.ruchir.dev/mcp/officer' \
DB_HOST=localhost \
python evals/runner.py

Citizen personas complete mobile OTP via the SMS gateway. The officer persona uses the admin password.

Local docker compose

ADMIN_PASSWORD='pick-something' \
PUBLIC_BASE_URL='http://localhost:8000' \
CITIZEN_MCP_URL='http://localhost:8001/mcp/citizen' \
OFFICER_MCP_URL='http://localhost:8002/mcp/officer' \
docker compose up --build -d

If container-to-container TCP fails in your environment:

docker compose -f docker-compose.yml -f docker-compose.sandbox.yml up --build -d
SurfaceLocal URL
Portal / docshttp://localhost:8000 and http://localhost:8000/docs/
Citizen MCPhttp://localhost:8001/mcp/citizen
Officer MCPhttp://localhost:8002/mcp/officer
Unified gatewayhttp://localhost:8080
SMS OTP inboxhttp://localhost:8000/__gateway/

Point MCP clients at the local MCP URLs the same way as the live ones. Set PUBLIC_BASE_URL and the MCP URLs so OAuth issuer and audience match what the client calls.

Design

See DESIGN.md in the repository for the three decisions that mattered: portal as sole writer of scheme truth, two MCP resource servers on one OAuth AS, and agent apply limited to three blocks. The note also records what we would redo next for age-proof uploads.