Skip to main content

Overview

The MCP (Model Context Protocol) API provides endpoints for managing MCP server configurations and OAuth authentication flows. You can:
  • List all configured MCP servers with status
  • Get detailed status for individual servers
  • Initiate OAuth login flows
  • Enable/disable servers
MCP servers extend the agent’s capabilities by providing additional tools and resources.

GET /api/v1/mcp/servers

List all configured MCP servers with their current status.

Request

curl -X GET http://127.0.0.1:8080/api/v1/mcp/servers \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

servers
array
Array of MCP server status objects.
name
string
Server name from configuration.
type
string
Server type: http, sse, or stdio.
enabled
boolean
Whether the server is enabled.
has_oauth
boolean
Whether the server supports OAuth authentication.
has_token
boolean
Whether an access token is stored for this server.
needs_login
boolean
true if the server has OAuth, is enabled, but has no token.
transport
string
Transport details (URL for HTTP/SSE, command for stdio).
total
integer
Total number of configured servers.

Example Response

{
  "servers": [
    {
      "name": "supabase",
      "type": "http",
      "enabled": true,
      "has_oauth": true,
      "has_token": true,
      "needs_login": false,
      "transport": "https://mcp.supabase.com"
    },
    {
      "name": "github",
      "type": "http",
      "enabled": true,
      "has_oauth": true,
      "has_token": false,
      "needs_login": true,
      "transport": "https://api.github.com/mcp"
    },
    {
      "name": "local-tools",
      "type": "stdio",
      "enabled": true,
      "has_oauth": false,
      "has_token": false,
      "needs_login": false,
      "transport": "python -m mcp_tools"
    }
  ],
  "total": 3
}

GET /api/v1/mcp//status

Get the status of a single MCP server.

Request

curl -X GET http://127.0.0.1:8080/api/v1/mcp/github/status \
  -H "Authorization: Bearer YOUR_TOKEN"
server
string
required
The MCP server name (URL path parameter).

Response

Returns a single MCP server status object (same structure as in the list response).
{
  "name": "github",
  "type": "http",
  "enabled": true,
  "has_oauth": true,
  "has_token": false,
  "needs_login": true,
  "transport": "https://api.github.com/mcp"
}

Error Responses

404 Not Found - Server does not exist:
{
  "detail": "MCP server 'unknown' not found"
}

POST /api/v1/mcp//login

Initiate OAuth login for an MCP server. Supports two flow types:
  1. Explicit OAuth - Servers with OAuthConfig in config
  2. Gateway-Mediated MCP OAuth - HTTP/SSE servers using MCP’s OAuth discovery

Request

curl -X POST http://127.0.0.1:8080/api/v1/mcp/github/login \
  -H "Authorization: Bearer YOUR_TOKEN"
server
string
required
The MCP server name to authenticate with.

Response

auth_url
string
The OAuth authorization URL. Open this in a browser to complete the login flow.
server_name
string
The server name that was requested.
status
string
Always "pending" when returning an auth URL.
tools_discovered
integer
Number of tools discovered (currently always 0 at login initiation).

Example Response

{
  "auth_url": "https://github.com/login/oauth/authorize?client_id=abc123&response_type=code&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2Fapi%2Fv1%2Fmcp%2Fcallback&state=abc123xyz&code_challenge=xyz789&code_challenge_method=S256&scope=repo%20user",
  "server_name": "github",
  "status": "pending",
  "tools_discovered": 0
}
The user must open the auth_url in a browser to authorize the application. After authorization, the OAuth provider redirects to the callback endpoint.

OAuth Flow Modes

1. Explicit OAuth

Servers with explicit OAuth configuration in config.json:
{
  "tools": {
    "mcp_servers": {
      "github": {
        "url": "https://api.github.com/mcp",
        "enabled": true,
        "oauth": {
          "auth_url": "https://github.com/login/oauth/authorize",
          "token_url": "https://github.com/login/oauth/access_token",
          "client_id": "your_client_id",
          "scopes": ["repo", "user"]
        }
      }
    }
  }
}

2. Gateway-Mediated MCP OAuth

HTTP/SSE servers without explicit OAuthConfig. The gateway:
  1. Discovers OAuth metadata from the MCP server
  2. Registers a client dynamically
  3. Returns an auth URL for the user
Example (Supabase):
{
  "tools": {
    "mcp_servers": {
      "supabase": {
        "url": "https://mcp.supabase.com",
        "enabled": true
      }
    }
  }
}

Error Responses

404 Not Found - Server does not exist:
{
  "detail": "MCP server 'unknown' not found"
}
400 Bad Request - Server has no OAuth support:
{
  "detail": "Server 'local-tools' has no URL or OAuth configuration"
}

GET /api/v1/mcp/callback

OAuth callback endpoint. This is called by the OAuth provider after the user authorizes the application.
This endpoint is public (no Bearer auth required) because the OAuth provider redirects the user’s browser here.

Request

The OAuth provider redirects to this endpoint with query parameters:
http://127.0.0.1:8080/api/v1/mcp/callback?code=abc123&state=xyz789
code
string
required
The authorization code from the OAuth provider.
state
string
required
The state token sent in the authorization request (for CSRF protection).
error
string
Error code if authorization failed.

Response

Returns an HTML page (not JSON):

Success

<!DOCTYPE html>
<html>
<head><title>Login Successful</title></head>
<body style="font-family:system-ui,sans-serif;...">
  <div style="text-align:center;...">
    <h1 style="color:#22c55e;">Login Successful!</h1>
    <p style="color:#64748b;">You can close this tab and return to grip.</p>
  </div>
</body>
</html>

Error

<html><body>
<h1>Login Failed</h1>
<p>Error: access_denied</p>
</body></html>
The access token is stored automatically and made available to the MCP server.

Token Storage

  • Explicit OAuth: Stored in ~/.grip/token_store.json
  • MCP OAuth: Stored in ~/.grip/mcp_clients.json (MCP library format)

POST /api/v1/mcp//enable

Enable a disabled MCP server.

Request

curl -X POST http://127.0.0.1:8080/api/v1/mcp/github/enable \
  -H "Authorization: Bearer YOUR_TOKEN"
server
string
required
The MCP server name to enable.

Response

{
  "server": "github",
  "status": "enabled"
}
Enabling a server updates config.json and takes effect immediately (no restart required).

POST /api/v1/mcp//disable

Disable an MCP server without deleting it.

Request

curl -X POST http://127.0.0.1:8080/api/v1/mcp/github/disable \
  -H "Authorization: Bearer YOUR_TOKEN"
server
string
required
The MCP server name to disable.

Response

{
  "server": "github",
  "status": "disabled"
}
Disabling a server:
  • Stops the agent from loading tools from that server
  • Does not delete the server configuration
  • Preserves stored OAuth tokens

Complete OAuth Flow Example

Python Client

import httpx
import webbrowser

base_url = "http://127.0.0.1:8080"
headers = {"Authorization": f"Bearer {token}"}

# 1. Initiate login
response = httpx.post(
    f"{base_url}/api/v1/mcp/github/login",
    headers=headers
)
data = response.json()

auth_url = data["auth_url"]
print(f"Opening browser to: {auth_url}")
webbrowser.open(auth_url)

# 2. User authorizes in browser
# 3. OAuth provider redirects to /api/v1/mcp/callback
# 4. Token is stored automatically

input("Press Enter after authorizing in the browser...")

# 5. Verify the server has a token
response = httpx.get(
    f"{base_url}/api/v1/mcp/github/status",
    headers=headers
)
status = response.json()

if status["has_token"]:
    print("✓ Login successful! Server is ready.")
else:
    print("✗ Login failed or incomplete.")

JavaScript/TypeScript Client

const baseUrl = 'http://127.0.0.1:8080';
const headers = { 'Authorization': `Bearer ${token}` };

// 1. Initiate login
const response = await fetch(`${baseUrl}/api/v1/mcp/github/login`, {
  method: 'POST',
  headers
});
const data = await response.json();

// 2. Open auth URL (in web app, use window.open or redirect)
window.open(data.auth_url, '_blank');

// 3. Poll for token after user returns
const checkToken = async () => {
  const statusResponse = await fetch(
    `${baseUrl}/api/v1/mcp/github/status`,
    { headers }
  );
  const status = await statusResponse.json();
  return status.has_token;
};

// Poll every 2 seconds
const interval = setInterval(async () => {
  if (await checkToken()) {
    console.log('✓ Login successful!');
    clearInterval(interval);
  }
}, 2000);

Security Considerations

PKCE (Proof Key for Code Exchange)

All OAuth flows use PKCE with SHA-256:
  • code_verifier: 64-byte random string
  • code_challenge: SHA-256 hash of verifier, base64-encoded
  • code_challenge_method: S256

State Parameter

CSRF protection via state tokens:
  • 32-byte random state token generated per flow
  • Stored server-side with 10-minute TTL
  • Validated on callback
  • Max 100 pending flows (oldest pruned)

Token Storage

Tokens are stored with restricted permissions:
$ ls -la ~/.grip/token_store.json
-rw------- 1 user user 1234 Feb 28 10:00 token_store.json

Redirect URI

Redirect URI is built from gateway config:
http://{gateway.host}:{gateway.port}/api/v1/mcp/callback
Example: http://127.0.0.1:8080/api/v1/mcp/callback
For production deployments with HTTPS reverse proxies, ensure the redirect URI matches the public URL. You may need to configure the OAuth provider with https://yourdomain.com/api/v1/mcp/callback.

Next Steps

Tools API

View tools provided by MCP servers

Management API

View system configuration

Build docs developers (and LLMs) love