Skip to main content
Authentication determines how your MCP server gets credentials to access external services. Choose the right pattern based on who provides the credentials and how they should be managed.
TypeWho provides credentialsExample
OAuthUser authorizes via OAuth flowLinear, GitHub, Slack
CredentialsUser enters in Gumstack UIOpenAI API key, custom tokens
NoneDeveloper sets via env varsShared API keys, public APIs
Auth type cannot be changed after server creation. Choose carefully!

OAuth

Best for services where users need to connect their own accounts. Gumstack handles the OAuth flow, token storage, and automatic refresh—you just implement the provider.

Configure your OAuth app

When registering an OAuth application with the third-party service (e.g., Linear, GitHub, Slack), set the redirect / callback URL to:
https://api.gumstack.com/auth/callback
This is the URL Gumstack uses to receive the authorization code after a user approves access.

Implement AuthProvider

Create a class that defines how to authenticate with your service:
import os
from mcp.gumstack import AuthProvider, TokenResponse

class LinearAuthProvider(AuthProvider):
    name = "linear"

    def get_url(self, redirect_uri: str, state: str) -> str:
        client_id = os.environ["LINEAR_CLIENT_ID"]
        return f"https://linear.app/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&state={state}&response_type=code&scope=read,write"

    async def exchange(self, code: str, redirect_uri: str) -> TokenResponse:
        # Exchange code for tokens with Linear API
        return TokenResponse(
            access_token=response["access_token"],
            refresh_token=response.get("refresh_token"),
            expires_in=response.get("expires_in")
        )

    async def refresh(self, refresh_token: str) -> TokenResponse:
        # Refresh expired token
        return TokenResponse(access_token=new_token)

    async def get_nickname(self, access_token: str) -> str:
        # Display name for connected account
        return "user@company.com"

Register with GumstackHost

Register your auth provider so Gumstack can use it:
from mcp.gumstack import GumstackHost

host = GumstackHost(mcp)
host.register_auth(LinearAuthProvider())
host.run()

Use in tools

Access the user’s credentials in your tools:
@mcp.tool()
async def list_issues() -> list[Issue]:
    creds = await get_credentials()
    token = creds["access_token"]
    # Call Linear API with token

Credentials

Best for services that use API keys or tokens that users provide themselves. Users enter their credentials in the Gumstack UI, and Gumstack securely stores and provides them to your server. Define the fields you need in config.yaml:
auth:
  type: cred
  credentials:
    - name: "api_key"
      label: "API Key"
      description: "Your OpenAI API key"
      placeholder: "sk-..."
      secret: true
Then access them in your tools:
@mcp.tool()
async def generate(prompt: str) -> str:
    creds = await get_credentials()
    api_key = creds["api_key"]
    # Call OpenAI API

None (Environment Variables)

Best for shared API keys that you (the developer) provide, or for public APIs that don’t require user-specific credentials. You set the credentials once in the Gumstack dashboard, and they’re available to all users.
auth:
  type: none
Set your credentials in the Gumstack dashboard under Environment Variables, then access them in your tools:
@mcp.tool()
def get_weather(city: str) -> Weather:
    creds = get_credentials()  # Note: sync, not async
    api_key = creds["api_key"]
    # Call weather API
With auth.type: none, get_credentials() is synchronous and reads directly from environment variables.

Reserved Environment Variables

Gumstack reserves certain environment variable prefixes for internal use. These will be rejected if you try to use them:
  • GUMLOOP_*
  • GUMSTACK_*