Graine AI

MCP authentication

Connect Claude, ChatGPT, Cursor, VS Code and Claude Code to your Graine workspace by signing in with Graine — no key to paste — or with an API key for clients that send headers.

Graine's MCP server lets an AI app work in your workspace. There are two ways to let it in:

  • Sign in with Graine — the app sends you to Graine, you sign in and allow it, and you're done. Nothing to copy, nothing to rotate. Use this whenever your app supports it: claude.ai, Claude Desktop, ChatGPT, Cursor, VS Code and Claude Code all do.
  • An API key in a request header — for clients that can't sign in, and for scripts. See Use an API key instead.
Server URLhttps://api.graine.ai/v2/mcp
Sign inOAuth 2.1 with PKCE. The app registers itself; there is no client ID or secret to enter
Or a keyAuthorization: Bearer gat_…

How signing in works

  1. Add https://api.graine.ai/v2/mcp to your AI app as a remote MCP server.
  2. The app opens Graine in your browser. Sign in if you aren't already.
  3. Graine shows what is asking — the app's name, the workspace, the role it will act with, and the address it sends you back to. Choose Allow.
  4. You're returned to the app, which is now connected. It keeps its own access up to date while you use it; you don't sign in again unless it goes unused for 30 days or you revoke it.

What a connected app can do

A connected app acts as you, in the one workspace you allowed it in:

  • It can do what you can do, and no more. Your role applies — Admin, Member, View only or a custom role (Keys and workspace roles). If you have View only access, the app can only read.
  • If you're limited to some agents, so is the app.
  • Changes still follow your workspace's approval rules: a change that would need an admin's approval from you needs it from the app too.
  • It can never create or revoke API keys.
  • If your role changes, the app follows within the hour. If you leave the workspace, the app stops within the hour.

Check where it sends you

An app names itself. Before you choose Allow, check the address on the consent screen — claude.ai, chatgpt.com, or an address on your own computer such as 127.0.0.1 for a desktop app you just started connecting. If you didn't start connecting an app, choose Deny.

To connect an app to a different workspace, switch to that workspace in Graine first, then connect again.

Connect your AI app

Claude (claude.ai and Claude Desktop)

Connectors you add in Claude work in claude.ai, Claude Desktop and Claude on mobile.

  1. Open Customize → Connectors, choose + Add, then Add custom connector.
  2. Name it Graine and enter https://api.graine.ai/v2/mcp.
  3. Keep the sign-in settings Claude detects. Leave the OAuth client ID and secret empty: Claude registers itself.
  4. Choose Add, then Connect, and allow it in Graine.

On Team and Enterprise plans, an Owner adds the connector once under Organization settings → Connectors; then each person opens Customize → Connectors, finds Graine and chooses Connect. Each person connects as themselves, with their own role.

ChatGPT

Add Graine as a custom MCP server in ChatGPT's settings for apps. Your workspace admin may need to allow custom servers first.

  1. Enter Graine as the name and https://api.graine.ai/v2/mcp as the server URL.
  2. Choose OAuth for authentication. Leave any client ID and secret empty.
  3. Create it. ChatGPT opens Graine; sign in and choose Allow.

Cursor

Add Graine to ~/.cursor/mcp.json for every project, or .cursor/mcp.json in one project:

{
  "mcpServers": {
    "graine": {
      "url": "https://api.graine.ai/v2/mcp"
    }
  }
}

Open Cursor's MCP settings, where Graine asks you to sign in. Choose to sign in, and allow it in Graine.

VS Code

Add Graine to .vscode/mcp.json in your workspace (or run MCP: Add Server and choose HTTP):

{
  "servers": {
    "graine": {
      "type": "http",
      "url": "https://api.graine.ai/v2/mcp"
    }
  }
}

Start the server. VS Code asks whether Graine may sign you in; allow it, then allow the connection in Graine.

Claude Code

claude mcp add --transport http graine https://api.graine.ai/v2/mcp

Then run /mcp in Claude Code, choose Graine and choose Authenticate. Add --scope user to the first command to use Graine in every project.

Other MCP clients

Any client that supports MCP authorization signs in the same way: give it https://api.graine.ai/v2/mcp and it finds the rest. A client that only runs local servers can reach Graine through mcp-remote, which signs in for it — for example in Claude Desktop's claude_desktop_config.json (it needs Node.js):

{
  "mcpServers": {
    "graine": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.graine.ai/v2/mcp"]
    }
  }
}

Manage connected apps

Every app you've connected is listed under API keys → Connected apps, with the address it signs in from, the role it acts with and when it was last used. People with View only access, who don't see API keys, find their own at /api-key/connected-apps in the dashboard.

  • Revoke stops the app within seconds: it can't read or change anything until someone connects it again.
  • Admins see every person's connected apps and can revoke any of them.
  • Connecting the same app again replaces the earlier connection — one per app per person.
  • Removing the app in the AI app (or signing out there) also ends the connection, when the app tells Graine.

Every connection and revocation is in the workspace's activity log, with who did it.

Use an API key instead

Use a key for a client that can't sign in, or for a script. The key acts with the role of the person who created it, within its scopes (Mint a key, Scopes). Keep it out of shared files, and revoke it if it leaks.

Cursor:

{
  "mcpServers": {
    "graine": {
      "url": "https://api.graine.ai/v2/mcp",
      "headers": { "Authorization": "Bearer gat_YOUR_KEY" }
    }
  }
}

VS Code, asking for the key once instead of storing it in the file:

{
  "inputs": [
    { "type": "promptString", "id": "graine-key", "description": "Graine API key", "password": true }
  ],
  "servers": {
    "graine": {
      "type": "http",
      "url": "https://api.graine.ai/v2/mcp",
      "headers": { "Authorization": "Bearer ${input:graine-key}" }
    }
  }
}

Claude Code:

claude mcp add --transport http graine https://api.graine.ai/v2/mcp \
  --header "Authorization: Bearer gat_YOUR_KEY"

Claude Desktop, through mcp-remote:

{
  "mcpServers": {
    "graine": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.graine.ai/v2/mcp", "--header", "Authorization:${GRAINE_AUTH}"],
      "env": { "GRAINE_AUTH": "Bearer gat_YOUR_KEY" }
    }
  }
}

For developers of MCP clients

Graine follows the MCP authorization specification. A request to the server without credentials is answered 401 with a pointer to the server's protected resource metadata, which names Graine's authorization server.

Protected resource metadatahttps://api.graine.ai/.well-known/oauth-protected-resource/v2/mcp (also at /.well-known/oauth-protected-resource)
Authorization serverhttps://www.graine.ai — metadata at /.well-known/oauth-authorization-server
Authorization endpointhttps://www.graine.ai/oauth/authorize
Token endpointhttps://www.graine.ai/api/oauth/token
Registration endpointhttps://www.graine.ai/api/oauth/register (dynamic client registration)
Revocation endpointhttps://www.graine.ai/api/oauth/revoke
Resourcehttps://api.graine.ai/v2/mcp
Scopeworkspace — act as the person who signs in

What the authorization server expects:

  • Public clients. Register with dynamic client registration; the answer is a client_id with token_endpoint_auth_method: "none" and no secret. Unused registrations are removed after a week; an unknown client_id at the token endpoint is 401 invalid_client, which means register again.
  • Redirect URIs must be https, or plain http to 127.0.0.1, [::1] or localhost. A loopback address matches on any port; every other address must match exactly. Other schemes are left out of a registration.
  • Authorization code with PKCE. code_challenge_method=S256 is required. A code is good once, for 60 seconds, and only with the redirect_uri, client and verifier of its request.
  • resource is https://api.graine.ai/v2/mcp when sent, in both the authorization and the token request. scope is workspace; offline_access is accepted alongside it.
  • Every authorization response carries iss — the issuer https://www.graine.ai, errors included.
  • Errors before anyone signs in (a missing code_challenge, an unknown scope) go straight back to an app on the person's computer — a loopback redirect URI. Any other app's error is shown to the person with a link back to the app, so a link to Graine can never send someone's browser to a site they didn't choose.
  • Tokens. Access tokens are bearer tokens that last an hour; treat them as opaque. Each refresh returns a new refresh token, and the old one stops working. A refresh token lasts 30 days from when it was issued. Presenting a refresh token that was already used ends the connection — the person has to sign in again.
  • Errors are the standard OAuth ones (invalid_grant, invalid_request, invalid_client, invalid_scope, invalid_target, temporarily_unavailable). After invalid_grant on a refresh, start a new sign-in.
  • Revocation takes the refresh token or the access token; either ends the connection.

On this page