Skip to main content
Glama

Setu — Sarvam MCP Server

CI Python License: MIT Coverage

Open-source Model Context Protocol server that exposes Sarvam AI's API surface as typed tools, so any MCP-capable agent (Claude Desktop, Cursor, Claude Code, or a custom LangGraph agent) can use Sarvam speech / translation / chat / document tools in minutes.

Live demo & write-up: https://sarvam-native.netlify.app/setu


Status — Milestone 7 (release-ready)

Feature-complete: all seven Sarvam tools over stdio + streamable-HTTP, each routed through the observability/reliability middleware seam, typed end-to-end, CI-gated (ruff, mypy --strict, 80%+ coverage, Docker build), containerised, and packaged for PyPI with a tag-triggered release workflow (trusted publishing). See DEMO.md for the 60-second demo storyboard. Everything runs in mock mode with no key; set SETU_MODE=live + SARVAM_API_KEY to hit real APIs.

Architecture

      MCP client (Claude Desktop / Cursor / Claude Code / LangGraph agent)
                        │  stdio   OR   streamable-HTTP (/mcp)
                        ▼
┌──────────────────────── SETU MCP SERVER (FastMCP) ───────────────────────┐
│  Tool layer — typed Pydantic in/out                                      │
│    setu_ping · sarvam_transcribe · sarvam_speak · sarvam_translate       │
│    sarvam_transliterate · sarvam_identify_language · sarvam_chat         │
│    sarvam_parse_document                                                 │
│                              │                                           │
│                              ▼   middleware seam (every call)            │
│      span(start) → rate-limit(token bucket) → retry/backoff →            │
│      dispatch → measure latency → compute INR cost → span attributes     │
│                       │                         │                        │
│                ┌──────┴──────┐           ┌──────┴───────┐                │
│                │ MODE: live  │           │ OTel spans   │                │
│                │      / mock │           │ cost+latency │                │
│                └──────┬──────┘           └──────────────┘                │
│           live │      │ mock                                             │
│                ▼      ▼                                                   │
│      sarvamai SDK    canned fixtures (no credits burned)                 │
└──────────────────────┼───────────────────────────────────────────────────┘
                       ▼
   Sarvam APIs — Saaras · Bulbul · Mayura · Sarvam-30B/105B · Parse

Every Sarvam call flows through one middleware seam so every tool call is observable and priced:

  • Retries: exponential backoff with jitter on 5xx/network errors; 4xx never retried except 429, which honours the server's Retry-After.

  • Rate limiting: a client-side token bucket per API key; remaining budget is reported as a span attribute.

  • Cost + latency telemetry: each call is wrapped in an OpenTelemetry span carrying setu.model, setu.endpoint, setu.latency_ms, input units, and a computed setu.cost_inr from a maintained INR rate card (pricing.py). Spans export to stderr in dev (SETU_OTEL_EXPORTER=console|none).

cost_inr is also returned on every tool result.

Milestone

Scope

State

1

Scaffold, config, structlog, FastMCP setu_ping over stdio

2

sarvam_transcribe + sarvam_speak, mock/live dispatch

3

Retry, rate-limit, cost/latency OTel telemetry middleware

4

translate, chat, transliterate, identify_language, parse_document

5

mypy --strict, 80%+ coverage gate, GitHub Actions CI

6

streamable-HTTP transport, Dockerfile, compose, architecture diagram

7

PyPI packaging + tag-triggered release workflow, demo storyboard

✅ this repo

Tools

Tool

Model

Key inputs

Output

setu_ping

message

server/version/mode echo

sarvam_transcribe

Saaras v3

audio_base64|audio_url, language_code=auto, mode=codemix

text, language, confidence, cost_inr

sarvam_speak

Bulbul v3

text, target_language_code, speaker

audio_base64 (WAV), chars, cost_inr

sarvam_translate

Mayura v1

input, target_language_code, source_language_code=auto

translated_text, source_language_code, cost_inr

sarvam_transliterate

Mayura

input, target_language_code, spoken_form

transliterated_text, cost_inr

sarvam_identify_language

text-lid

input

language_code, script_code, cost_inr

sarvam_chat

Sarvam-105B/30B

messages, model, tools, tool_choice

content, tool_calls, usage, cost_inr

sarvam_parse_document

Parse

file_base64|file_url

pages, fields, tables, cost_inr

Every result also carries latency_ms and request_id. Try them in mock mode with no key. To go live, set SETU_MODE=live and SARVAM_API_KEY, then install the SDK extra: pip install -e '.[live]'. (Live sarvam_parse_document uses Sarvam's job-based Document Digitization API, wired in a later milestone; mock is complete.)

Related MCP server: sarvam-tools

Quickstart

Once published, install from PyPI and launch with no clone:

pip install setu-mcp        # or: uvx setu-mcp
setu                        # stdio; or: setu --transport streamable-http

To develop from source:

# 1. Create a virtualenv and install (editable, with dev extras)
python3 -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'

# 2. Copy the env template (defaults to mock mode — no key needed)
cp .env.example .env

# 3. Run the server over stdio
setu            # or: python -m setu.server

# 4. Run the tests
pytest

setu speaks the MCP protocol on stdout, so it looks like it "hangs" — that's correct; it's waiting for an MCP client. Logs go to stderr as JSON. Press Ctrl-C to stop.

Transports

Setu serves the same tools over two transports from one FastMCP app:

setu                              # stdio (local IDE / desktop agents; default)
setu --transport streamable-http  # HTTP endpoint at http://127.0.0.1:8000/mcp

Configure the HTTP bind with SETU_HTTP_HOST / SETU_HTTP_PORT.

Docker

# Build and run the HTTP server (mock mode) on http://localhost:8000/mcp
docker build -t setu-mcp .
docker run --rm -p 8000:8000 setu-mcp

# Or via compose
docker compose up --build

# Live mode
docker run --rm -p 8000:8000 -e SETU_MODE=live -e SARVAM_API_KEY=sk_... setu-mcp

The image is a multi-stage build running as a non-root user; it defaults to the streamable-HTTP transport. Override with docker run ... setu --transport stdio.

Configuration

All config is environment-driven (pydantic-settings); secrets never get hardcoded.

Variable

Default

Meaning

SETU_MODE

mock

mock serves fixtures (no credits); live calls Sarvam (milestone 2+).

SETU_SERVER_NAME

setu

Name advertised to MCP clients.

SETU_LOG_LEVEL

INFO

structlog level.

SETU_RATE_LIMIT_PER_MINUTE

60

Token-bucket refill rate per API key.

SETU_RATE_LIMIT_TIMEOUT_S

10

Max seconds to wait for a token before erroring.

SETU_MAX_RETRIES

3

Total attempts per Sarvam call (retry cap).

SETU_OTEL_EXPORTER

console

Span exporter: console (stderr) or none.

SETU_HTTP_HOST

127.0.0.1

Bind host for the streamable-HTTP transport.

SETU_HTTP_PORT

8000

Bind port for the streamable-HTTP transport.

SARVAM_API_KEY

Sarvam key; only needed in live mode. Get one at dashboard.sarvam.ai.

Connect to Claude Desktop

  1. Find the absolute path to the setu entrypoint inside your venv:

    source .venv/bin/activate
    which setu      # e.g. /Users/you/setu-mcp/.venv/bin/setu
  2. Open Claude Desktop → Settings → Developer → Edit Config. This opens claude_desktop_config.json. Add Setu under mcpServers:

    {
      "mcpServers": {
        "setu": {
          "command": "/ABSOLUTE/PATH/TO/setu-mcp/.venv/bin/setu",
          "env": { "SETU_MODE": "mock" }
        }
      }
    }

    (On Windows the path ends in \.venv\Scripts\setu.exe.)

  3. Fully quit and reopen Claude Desktop. Click the tools/🔌 icon in the chat box — you should see setu listed with the setu_ping tool.

  4. Ask Claude: "Use the setu_ping tool with message 'it works'." You should get back a typed result showing ok: true, the server name, version, and mode: mock.

If the server doesn't appear, check Claude Desktop's MCP logs (~/Library/Logs/Claude/mcp*.log on macOS) — Setu's JSON logs on stderr are captured there.

Layout

setu-mcp/
├─ pyproject.toml          # package + tooling (ruff, mypy, pytest, coverage)
├─ Dockerfile              # multi-stage, non-root, HTTP by default
├─ docker-compose.yml      # one-command local run
├─ .github/workflows/ci.yml# ruff + mypy + pytest + docker build
├─ .env.example            # config template (mock by default)
├─ src/setu/
│  ├─ config.py            # SetuSettings + SarvamSettings (pydantic-settings)
│  ├─ logging.py           # structlog → stderr, JSON, request ids
│  ├─ modes.py             # live vs mock dispatch
│  ├─ errors.py            # typed errors + retryable classification
│  ├─ pricing.py           # INR rate card + cost estimator
│  ├─ telemetry.py         # OpenTelemetry setup (stderr exporter) + tracer
│  ├─ middleware.py        # token-bucket rate limiter + retry/backoff
│  ├─ sarvam_client.py     # async wrapper; span→rate-limit→retry→cost seam
│  ├─ fixtures/            # deterministic mock responses
│  ├─ app.py               # shared FastMCP app + Sarvam client + settings
│  ├─ tools/               # one module per tool (health, transcribe, speak,
│  │                       #   translate, transliterate, identify_language,
│  │                       #   chat, parse_document) — each typed + registered
│  └─ server.py            # transport entrypoint (registers tools, runs stdio)
└─ tests/
   ├─ test_ping.py         # health-check + registration
   ├─ test_tools.py        # transcribe/speak (mock) + skipped live smoke test
   ├─ test_tools_m4.py     # translate/transliterate/langID/chat/parse (mock)
   └─ test_middleware.py   # rate limiter, retry (5xx/4xx/429), pricing, spans

Releasing

Releases are automated. Tagging a version builds the sdist + wheel, creates a GitHub Release, and publishes to PyPI via Trusted Publishing (OIDC — no token stored):

git tag v0.1.0
git push origin v0.1.0

One-time PyPI setup: at pypi.org → Publishing, add a trusted publisher for this repo (workflow release.yml, environment pypi).

License

MIT © 2026 Manasa SB

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • OCR, transcription, file extraction, and image generation for AI agents via MCP.

  • MCP server exposing the Backtest360 engine API as tools for AI agents.

  • Manage SRG+ hubs, channels, content, assets, users, and workspaces from any MCP-aware AI agent.

View all MCP Connectors

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/manasasb2000/setu-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server