MCP Hub
Back to servers

rest_api_mcp

A Model Context Protocol (MCP) server for authenticated REST APIs. Drop it into any project, point it at your API, and let AI agents call endpoints — with auto-login, 2FA support, Swagger spec fetch, and fuzzy endpoint search — all without writing a single line of auth code.

glama
Stars
3
Forks
3
Updated
Apr 16, 2026
Validated
Apr 18, 2026

rest-api-mcp

A Model Context Protocol (MCP) server for authenticated REST APIs.
Drop it into any project, point it at your API, and let AI agents call endpoints — with auto-login, 2FA support, Swagger spec fetch, and fuzzy endpoint search — all without writing a single line of auth code.


Table of Contents


Features

CapabilityDescription
Auto-loginLogs in automatically before every request; re-logins when token expires
Token caching20-second TTL cache — survives rapid sequential calls
Auto-discoveryFinds the login endpoint by scanning the Swagger spec (no config needed)
Auto token detectionTries 9 common token paths (data.access_token, accessToken, token, …)
2FA / OTP supportTwo-step auth: login → verify-otp, session identifiers forwarded automatically
Extra login fieldssource, userRole, channel, device_id — any field, via JSON env var
Fuzzy endpoint searchFind endpoints by keyword across path, summary, description, tags, operationId
Swagger spec fetchRetrieve and inspect the full OpenAPI spec
SSL bypassOptional for staging/dev environments with self-signed certs
Response truncationConfigurable size limit to keep responses in context

Installation

Option A — Use via npx (recommended)

No installation needed. Add this to your project's .vscode/mcp.json and VS Code will download and run the package automatically:

{
  "command": "npx",
  "args": ["-y", "rest-api-mcp"]
}

This always uses the latest published version from npm. See VS Code mcp.json Examples for a full config.

Option B — Use locally (for development / offline)

git clone https://github.com/Muhammed-AbdelGhany/rest_api_mcp
cd rest_api_mcp
npm install && npm run build

Then point VS Code at the local build:

{
  "command": "node",
  "args": ["/path/to/rest_api_mcp/build/index.js"]
}

Quick Start

Add this to your project's .vscode/mcp.json:

{
  "servers": {
    "my-api": {
      "command": "npx",
      "args": ["-y", "rest-api-mcp"],
      "env": {
        "REST_BASE_URL": "https://api.example.com/api/v1",
        "API_EMAIL": "user@example.com",
        "API_PASSWORD": "yourpassword",
        "API_SWAGGER_URL": "https://api.example.com/docs-json"
      }
    }
  }
}

That's it. The agent can now:

  1. Search for endpoints by keyword
  2. Call any endpoint with automatic authentication
  3. Fetch the full OpenAPI spec for schema inspection

Configuration

All configuration is done via environment variables in mcp.json. No code changes required.

Minimum required

VariableDescription
REST_BASE_URLBase URL of the API (no trailing slash)
API_EMAILLogin email
API_PASSWORDLogin password

Strongly recommended

VariableDescription
API_SWAGGER_URLOpenAPI/Swagger JSON URL — enables fetch_spec, search_endpoints, and auto-login-endpoint discovery

Optional

See Environment Variables Reference for the full list.


Tools

search_endpoints

Fuzzy-search the API spec by keyword. Returns matching endpoints with method, path, summary, tags, and required parameters. Use this before request when you don't know the exact path.

Input:

FieldTypeRequiredDescription
querystringKeywords to search for
limitnumberMax results (default: 10)

Example — Find order-related endpoints:

search_endpoints("orders list customer")

Response:

Found 6 match(es) for "orders list customer", showing top 5:

1. GET /customers/{id}/orders
   Summary: List all orders for a customer
   Tags: Orders, Customers
   Required params: path:id

2. GET /orders
   Summary: List orders with optional filters
   Tags: Orders
   Required params: query:status, query:page

3. POST /orders/search
   Summary: Search orders by multiple criteria
   Tags: Orders
   Required params: body
...

request

Make an authenticated API call. Handles login automatically — re-logins transparently if the token is expired.

Input:

FieldTypeRequiredDescription
methodstringGET, POST, PUT, PATCH, DELETE
endpointstringPath relative to REST_BASE_URL, e.g. /users/profile
bodyobjectRequest body for POST/PUT/PATCH
headersobjectExtra headers to merge
skip_authbooleanSet true to skip the Authorization header

Response shape:

{
  "status": 200,
  "statusText": "OK",
  "timing_ms": 312,
  "login_data": { ... },
  "response": { ... }
}

login_data contains the full login response — useful for IDs like userId, orgId, tenantId returned at login that you need for subsequent requests.

Example — GET current user profile:

request("GET", "/users/me")

Example — POST with filters:

request("POST", "/orders/search", {
  "status": "pending",
  "from": "2025-01-01",
  "limit": 20
})

Example — PATCH to update a resource:

request("PATCH", "/products/42", {
  "price": 9.99,
  "inStock": true
})

Example — Public endpoint (no auth):

request("GET", "/health", skip_auth=true)

fetch_spec

Fetch the full OpenAPI/Swagger JSON spec for schema inspection, DTO discovery, or understanding available endpoints.

Input:

FieldTypeRequiredDescription
urlstringOverride spec URL. Falls back to API_SWAGGER_URL env var

Example:

fetch_spec()

Returns the raw OpenAPI JSON (truncated to REST_RESPONSE_SIZE_LIMIT if large).


Authentication Flows

Standard login

The most common case — email + password, token returned directly.

{
  "REST_BASE_URL": "https://api.example.com/api/v1",
  "API_EMAIL": "user@example.com",
  "API_PASSWORD": "secret",
  "API_SWAGGER_URL": "https://api.example.com/docs-json"
}

The server auto-discovers the login endpoint by scanning the Swagger spec for the first POST path containing "login". Override if needed:

"API_LOGIN_ENDPOINT": "/auth/sign-in"

Login with extra credentials

Some APIs require fields beyond email and password in the login request body — for example a role to specify what type of user is logging in, a source to indicate which client platform is making the request, a channel, a tenantId, etc.

Set API_LOGIN_CREDENTIALS to a JSON object string containing any extra fields you need. They are merged into the login POST body alongside email and password:

"API_LOGIN_CREDENTIALS": "{\"role\": \"admin\"}"

What gets sent to the login endpoint:

{
  "email": "admin@acme.com",
  "password": "secret",
  "role": "admin"
}

Multiple extra fields work the same way:

"API_LOGIN_CREDENTIALS": "{\"role\": \"viewer\", \"source\": \"web\", \"tenantId\": \"acme\"}"

What gets sent:

{
  "email": "viewer@acme.com",
  "password": "secret",
  "role": "viewer",
  "source": "web",
  "tenantId": "acme"
}

Note: The field names are entirely up to your API. Check its Swagger spec or docs to see what the login endpoint accepts.


Two-factor authentication (2FA)

Some APIs require a second verification step after the initial login — the server returns a one-time code to the user's email or phone, and you must submit it to a separate endpoint to receive the actual JWT.

Flow:

Step 1 — Login
  POST /auth/login  { email, password }
  ← 200: { session_token: "tmp_abc", message: "OTP sent to email" }

Step 2 — Verify OTP
  POST /auth/verify-otp  { email, otp: "482019", session_token: "tmp_abc" }
  ← 200: { accessToken: "eyJhbGci..." }

The three env vars that drive this:

"API_VERIFY_ENDPOINT": "/auth/verify-otp",
"API_OTP": "482019",
"API_LOGIN_CREDENTIALS": "{\"platform\": \"web\"}"

API_VERIFY_ENDPOINT — The path of the second step. When this is set, the server automatically performs both steps before attaching a token to your request.

API_OTP — The OTP value to submit. For staging environments this is usually a fixed test code provided by the API team. For production you'd need to retrieve the live code from your email and set it here.

Session carry-forward — Session identifiers returned by login step 1 (e.g. session_token, requestId, temp_token, nonce, transactionId) are automatically detected and forwarded to the verify endpoint. You do not need to configure this manually.

The full body sent to the verify endpoint looks like:

{
  "email": "user@acme.com",
  "otp": "482019",
  "session_token": "tmp_abc"   ← auto-carried from step 1
}

API_VERIFY_CREDENTIALS — If your verify endpoint requires extra fields that aren't session identifiers or the OTP, add them here:

"API_VERIFY_CREDENTIALS": "{\"client_id\": \"web-app\"}"

What gets sent:

{
  "email": "user@acme.com",
  "otp": "482019",
  "session_token": "tmp_abc",
  "client_id": "web-app"    ← from API_VERIFY_CREDENTIALS
}

Multi-API Setup

Run multiple independent server instances — one per API — in the same mcp.json. Each instance runs its own auth session, token cache, and spec cache independently.

In this example, shop-api uses a simple role-based login and analytics-api uses 2FA:

{
  "servers": {
    "shop-api": {
      "command": "npx",
      "args": ["-y", "rest-api-mcp"],
      "env": {
        "REST_BASE_URL": "https://api.acme-shop.com/v1",
        "API_EMAIL": "admin@acme-shop.com",
        "API_PASSWORD": "s3cr3t",
        "API_LOGIN_CREDENTIALS": "{\"role\": \"admin\"}",
        "API_SWAGGER_URL": "https://api.acme-shop.com/docs-json"
      }
    },
    "analytics-api": {
      "command": "npx",
      "args": ["-y", "rest-api-mcp"],
      "env": {
        "REST_BASE_URL": "https://analytics.acme.com/api/v2",
        "API_EMAIL": "analyst@acme.com",
        "API_PASSWORD": "s3cr3t",
        "API_LOGIN_ENDPOINT": "/auth/sign-in",
        "API_VERIFY_ENDPOINT": "/auth/verify-otp",
        "API_OTP": "482019",
        "API_SWAGGER_URL": "https://analytics.acme.com/openapi.json"
      }
    }
  }
}

VS Code mcp.json Examples

Minimal

{
  "servers": {
    "my-api": {
      "command": "npx",
      "args": ["-y", "rest-api-mcp"],
      "env": {
        "REST_BASE_URL": "https://api.example.com/v1",
        "API_EMAIL": "user@example.com",
        "API_PASSWORD": "secret"
      }
    }
  }
}

Full (all options)

{
  "servers": {
    "my-api": {
      "command": "npx",
      "args": ["-y", "rest-api-mcp"],
      "env": {
        "REST_BASE_URL": "https://api.example.com/v1",
        "REST_ENABLE_SSL_VERIFY": "false",
        "REST_RESPONSE_SIZE_LIMIT": "150000",
        "API_EMAIL": "user@example.com",
        "API_PASSWORD": "secret",
        "API_LOGIN_ENDPOINT": "/auth/login",
        "API_LOGIN_CREDENTIALS": "{\"source\":\"mobile\"}",
        "API_VERIFY_ENDPOINT": "/auth/verify-otp",
        "API_OTP": "123456",
        "API_VERIFY_CREDENTIALS": "{\"device_id\":\"abc\"}",
        "API_TOKEN_PATH": "data.access_token",
        "API_SWAGGER_URL": "https://api.example.com/docs-json"
      }
    }
  }
}

How It Works

Agent says: "show me pending orders"
     │
     ▼
search_endpoints("orders pending list")
     │  Fetches Swagger spec, scores every endpoint by keyword match
     │  Returns: GET /orders  ← best match
     ▼
request("GET", "/orders?status=pending")
     │
     ├─ Token cache valid? ──yes──► attach Bearer token
     │
     └─ Cache expired/empty?
           │
           ├─ Step 1: POST /auth/login  {email, password, ...LOGIN_CREDENTIALS}
           │          ◄── 200: {data: {access_token: "eyJ..."}}
           │
           ├─ [if VERIFY_ENDPOINT set]
           │   Step 2: POST /auth/verify-otp  {email, otp, ...session_tokens}
           │            ◄── 200: {accessToken: "eyJ..."}
           │
           ├─ Auto-detect token path from response
           ├─ Cache token for 20s
           └─ attach Bearer token
     │
     ▼
GET /orders?status=pending
     Authorization: Bearer eyJ...
     ◄── 200: {total: 47, data: [{id: 1, status: "pending", ...}, ...]}

Environment Variables Reference

VariableRequiredDefaultDescription
REST_BASE_URLBase API URL, no trailing slash
API_EMAIL✅*Login email (*required for authenticated endpoints)
API_PASSWORD✅*Login password
API_SWAGGER_URLOpenAPI JSON URL for fetch_spec, search_endpoints, and login auto-discovery
API_LOGIN_ENDPOINTauto-discoveredOverride login path, e.g. /auth/sign-in
API_LOGIN_CREDENTIALSJSON object of extra fields merged into the login POST body alongside email/password. Use for role, source, tenantId, etc. Example: {"role":"admin"}
API_VERIFY_ENDPOINTPath of the 2FA/OTP verify step. Setting this enables two-step auth. Example: /auth/verify-otp
API_OTPThe OTP code to submit to API_VERIFY_ENDPOINT. On staging this is typically a fixed test code.
API_VERIFY_CREDENTIALSJSON object of extra fields merged into the verify POST body, beyond the auto-carried session identifiers and OTP. Example: {"client_id":"web-app"}
API_TOKEN_PATHauto-detectedDot-path to token in login/verify response, e.g. data.access_token
REST_ENABLE_SSL_VERIFYtrueSet false to skip TLS cert validation (dev/staging only)
REST_RESPONSE_SIZE_LIMIT100000Max response characters before truncation

Auto-detected token paths (tried in order): data.access_token · access_token · data.token · token · data.accessToken · accessToken · data.data.access_token · result.access_token · result.token

Auto-forwarded session fields (2FA step 1 → step 2): session_token · sessionToken · session · request_id · requestId · temp_token · tempToken · verification_token · verificationToken · challenge · nonce · transaction_id · transactionId


Troubleshooting

Login failed: Could not find token
The login response uses an unusual token path. Set API_TOKEN_PATH explicitly:

"API_TOKEN_PATH": "result.data.jwt"

2FA verify fails with 401
The verify endpoint may need the OTP as a different field name. Use API_VERIFY_CREDENTIALS:

"API_VERIFY_CREDENTIALS": "{\"code\": \"123456\"}"

And leave API_OTP unset if the field name isn't otp.

search_endpoints returns no matches

  • Make sure API_SWAGGER_URL is set and reachable
  • Try broader keywords: "inventory" instead of "getInventory"
  • The spec may be truncated — use fetch_spec to check

SSL errors on staging

"REST_ENABLE_SSL_VERIFY": "false"

Response truncated
Increase the limit:

"REST_RESPONSE_SIZE_LIMIT": "500000"

License

MIT

Reviews

No reviews yet

Sign in to write a review