MCP Server
Connect any AI agent or app to Setu over the Model Context Protocol — same capabilities as the REST API, exposed as tools.
https://setu.theabhipatel.com/api/mcpOverview
The Model Context Protocol (MCP) is an open standard that lets AI assistants (Claude Desktop, Cursor, Cline, custom agents, and more) call external tools. Setu hosts a remote MCP server, so any compatible client can send messages, manage conversations and groups, search users, upload files, and manage webhooks — all on behalf of the user that owns the API key.
Hosted & remote
One URL. No install, no local process to run.
Key or OAuth
Static tap_setu_ key or OAuth 2.1 — same scopes & limits.
Full API surface
Every public API action is available as a tool.
Looking for raw HTTP endpoints instead? See the REST API documentation.
Connection
| Endpoint URL | https://setu.theabhipatel.com/api/mcp |
| Transport | Streamable HTTP |
| Auth | Authorization: Bearer <token> |
| Version | 1.0.0 (reported in serverInfo during initialize) |
Every request must carry a bearer token. Setu supports two ways to obtain one — a long-lived static API key or an OAuth 2.1 access token. Both authenticate as a single Setu user and are constrained by the same permission scopes and rate limits. See to pick the right one.
Treat tokens like passwords. Store them in your client's config/secret store — never commit them to a repo.
Authentication
The MCP server accepts two authentication methods. Both resolve to the same Setu user, the same , and the same rate limits — pick based on your client and who the agent acts for.
| Method | Best for | How the agent gets access |
|---|---|---|
| Static Bearer Token API key | Personal automation and clients you control yourself. | You create a key in the dashboard and paste it into the client config. |
| OAuth 2.1 authorization code + PKCE | Third-party agents and apps that act on behalf of other Setu users. | The user logs in and approves a consent screen; the client receives a scoped, expiring token automatically. |
Option A — Static Bearer Token (API key)
The simplest method. Create a key in API Keys, grant it the scopes you want the agent to use, and send it on every request:
Authorization: Bearer tap_setu_YOUR_KEY_HEREKeys start with tap_setu_ and are long-lived (they only stop working if you disable them or set an expiry). The full key is shown once at creation — store it immediately. This is the right choice when you own both the agent and the account it acts as. See for ready-to-paste config.
Option B — OAuth 2.1
Use OAuth when an agent or app needs to act on behalf of a user without ever handling a static key. The user authorizes through a Setu consent screen and your client receives a scoped, expiring access token. Setu implements OAuth 2.1 with mandatory PKCE (S256) and Dynamic Client Registration.
Most MCP clients with built-in OAuth (e.g. Claude, Cursor) run this whole flow automatically — just point them at the MCP URL with no auth header and follow the browser prompt. The steps below are what happens under the hood, and what to implement for a custom client.
Discovery
Clients discover the endpoints from the standard metadata document (RFC 8414):
GET https://setu.theabhipatel.com/.well-known/oauth-authorization-server{
"issuer": "https://setu.theabhipatel.com",
"authorization_endpoint": "https://setu.theabhipatel.com/oauth/authorize",
"token_endpoint": "https://setu.theabhipatel.com/api/oauth/token",
"registration_endpoint": "https://setu.theabhipatel.com/api/oauth/register",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none", "client_secret_post"]
}Step 1 — Register a client (RFC 7591)
Register once to get a client_id. No authentication is required. Redirect URIs must be localhost or HTTPS.
curl -X POST https://setu.theabhipatel.com/api/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "My MCP Client",
"redirect_uris": ["http://localhost:9999/oauth/callback"],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none",
"scope": "messages:send messages:read conversations:read"
}'{
"client_id": "setu_oac_...",
"redirect_uris": ["http://localhost:9999/oauth/callback"],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}Public clients use token_endpoint_auth_method: "none" (no secret). For a confidential client, use client_secret_post and a client_secret (prefix setu_ocs_) is returned.
Step 2 — Authorize (with PKCE)
Generate a PKCE code_verifier and its S256 code_challenge, then send the user to the authorization endpoint in a browser:
GET https://setu.theabhipatel.com/oauth/authorize
?client_id=setu_oac_...
&redirect_uri=http://localhost:9999/oauth/callback
&response_type=code
&scope=messages:send%20messages:read%20conversations:read
&state=RANDOM_CSRF_VALUE
&code_challenge=PKCE_S256_CHALLENGE
&code_challenge_method=S256The user signs in (if needed) and approves the requested scopes. Setu then redirects back to your redirect_uri with a one-time authorization code (the state is echoed back — verify it):
http://localhost:9999/oauth/callback?code=setu_ocd_...&state=RANDOM_CSRF_VALUEStep 3 — Exchange the code for tokens
POST the code and the original code_verifier to the token endpoint (accepts JSON or x-www-form-urlencoded):
curl -X POST https://setu.theabhipatel.com/api/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "setu_ocd_...",
"client_id": "setu_oac_...",
"redirect_uri": "http://localhost:9999/oauth/callback",
"code_verifier": "YOUR_PKCE_VERIFIER"
}'{
"access_token": "setu_oat_...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "setu_ort_...",
"scope": "messages:send messages:read conversations:read"
}Step 4 — Call the MCP server
Send the access token exactly like a static key — same header, same tools:
Authorization: Bearer setu_oat_...Step 5 — Refresh when it expires
Access tokens last 1 hour; refresh tokens last 30 days. When an access token expires, exchange the refresh token for a new pair (the old refresh token is rotated out):
curl -X POST https://setu.theabhipatel.com/api/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "refresh_token",
"refresh_token": "setu_ort_...",
"client_id": "setu_oac_..."
}'| Discovery | /.well-known/oauth-authorization-server |
| Registration | /api/oauth/register |
| Authorization | /oauth/authorize |
| Token | /api/oauth/token |
| Access token TTL | 1 hour |
| Refresh token TTL | 30 days (rotated on use) |
Client Setup
The snippets below use a static API key. If your client supports OAuth, you can instead point it at the URL with no header and it will run the for you in the browser:
{
"mcpServers": {
"setu-chat": {
"url": "https://setu.theabhipatel.com/api/mcp"
}
}
}Clients with native remote MCP support (e.g. Cursor)
Point the client at the URL and attach the auth header:
{
"mcpServers": {
"setu-chat": {
"url": "https://setu.theabhipatel.com/api/mcp",
"headers": {
"Authorization": "Bearer tap_setu_YOUR_KEY_HERE"
}
}
}
}Claude Desktop / stdio-only clients
Use the mcp-remote bridge to connect a stdio client to the remote server with headers:
{
"mcpServers": {
"setu-chat": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://setu.theabhipatel.com/api/mcp",
"--header", "Authorization: Bearer tap_setu_YOUR_KEY_HERE"
]
}
}
}Test it with the MCP Inspector
npx @modelcontextprotocol/inspector
# Transport: Streamable HTTP
# URL: https://setu.theabhipatel.com/api/mcp
# Header: Authorization: Bearer tap_setu_YOUR_KEY_HERETools Reference
Parameters marked * are required. Each tool requires the listed permission scope on your API key; calling a tool without its scope returns a PERMISSION_DENIED error.
Messages
| Tool | Scope | Parameters |
|---|---|---|
send_messageSend a message to a conversation. | messages:send | conversation_id*, content*, message_type, reply_to |
list_messagesList messages in a conversation (paginated, newest-first cursor). | messages:read | conversation_id*, before, limit |
edit_messageEdit a message you sent. | messages:edit | message_id*, content* |
delete_messageSoft-delete a message you sent. | messages:delete | message_id* |
Conversations
| Tool | Scope | Parameters |
|---|---|---|
list_conversationsList all conversations the key owner belongs to. | conversations:read | — |
get_conversationGet a single conversation with its members. | conversations:read | conversation_id* |
create_conversationCreate a private chat or group. Returns existing private chat if one exists. | conversations:create | type*, member_ids*, name, description |
Groups & Members
| Tool | Scope | Parameters |
|---|---|---|
add_membersAdd members to a group. | members:add | group_id*, user_ids* |
list_membersList a group's members. | members:list | group_id* |
remove_memberRemove a member (self, or others if admin/owner). | members:remove | group_id*, user_id* |
Users
| Tool | Scope | Parameters |
|---|---|---|
search_usersSearch users by name or username (min 2 chars). | users:search | q*, limit |
get_user_profileGet a user's public profile. | users:profile | user_id* |
Files
| Tool | Scope | Parameters |
|---|---|---|
upload_fileUpload a file (base64) to a conversation. Max 10MB. | files:upload | conversation_id*, file_name*, file_base64*, mime_type |
Account
| Tool | Scope | Parameters |
|---|---|---|
get_accountGet the authenticated user's account info. | account:read | — |
Webhooks
| Tool | Scope | Parameters |
|---|---|---|
list_webhooksList your webhooks. | webhooks:read | — |
create_webhookCreate a webhook subscription. | webhooks:manage | name*, url*, events* |
update_webhookUpdate a webhook. | webhooks:manage | webhook_id*, name, url, events, is_active |
delete_webhookDelete a webhook. | webhooks:manage | webhook_id* |
Example Prompts
Once connected, you can drive Setu in natural language. The agent picks the right tools automatically:
Rate Limits
MCP tool calls share the exact same rate limit and usage tracking as the REST API — each tool call counts as a single request against your key's per-minute limit. See the REST docs for per-plan limits, and Usage & Analytics to monitor consumption.
Troubleshooting
| Symptom | Cause & Fix |
|---|---|
| 401 / connection rejected | Missing or invalid token. Ensure an Authorization: Bearer header is set with an active static key (tap_setu_…) or a valid OAuth access token (setu_oat_…). |
| OAuth token stopped working after ~1 hour | Access tokens expire after 1 hour. Use the refresh_token grant to get a new pair — see . |
PERMISSION_DENIED from a tool | The token lacks that tool's scope. For a static key, add the scope in API Keys; for OAuth, request the scope during authorization. |
RATE_LIMIT_EXCEEDED | Too many calls per minute. Slow down or upgrade your plan. |
| Tools not appearing | Confirm the transport is “Streamable HTTP” and the URL is exactly https://setu.theabhipatel.com/api/mcp. |