Claude
Skills
Sign in
Back

setup-mcp-auth

Included with Lifetime
$97 forever

Configure authentication for an existing FastMCP server

AI Agents

What this skill does


# Setup MCP Authentication

Configure authentication and authorization for an existing FastMCP server.

## Usage

```bash
/setup-mcp-auth [auth-type]
```

## Arguments

- `[auth-type]`: Optional - Type of authentication (api-key, oauth, custom)

## Execution Instructions for Claude Code

When this command is run:

1. **Locate the FastMCP server** in the current project
2. **Determine authentication requirements**
3. **Configure authentication** based on selected type
4. **Add authorization rules** to tools if needed
5. **Generate environment configuration**

## Interactive Session Flow

### 1. Locate Server

```
Looking for FastMCP server...

Found: src/server.ts

Is this the correct server file? (yes/no):
```

### 2. Authentication Type

```
What type of authentication do you want to configure?

1. API Key - Simple header-based authentication
2. Role-Based - API key with user roles
3. OAuth 2.0 - Google or custom OAuth provider
4. JWT Validation - Validate external JWT tokens
5. Custom - Implement your own authentication logic

Select (1-5):
```

### 3. API Key Configuration

For API Key (option 1):
```
API Key Configuration

Header name for API key [default: x-api-key]:

How should API keys be stored?
1. Environment variable
2. Database lookup
3. Static configuration

Select (1-3):
```

### 4. Role-Based Configuration

For Role-Based (option 2):
```
Role-Based Authentication

What roles do you need?
Example: admin,user,readonly

Roles (comma-separated):
```

```
How are roles determined?
1. From request header (e.g., x-role)
2. From API key lookup
3. From JWT claims

Select (1-3):
```

### 5. OAuth Configuration

For OAuth 2.0 (option 3):
```
OAuth Provider

Which OAuth provider?
1. Google
2. GitHub (custom setup)
3. Custom OAuth provider

Select (1-3):
```

For Google:
```
Google OAuth Setup

You'll need:
- Google Cloud Console project
- OAuth 2.0 credentials (Client ID and Secret)
- Authorized redirect URIs configured

Base URL for your server:
Example: https://your-server.com

Base URL:
```

```
OAuth scopes (comma-separated):
Default: openid,profile,email

Scopes [press Enter for default]:
```

### 6. JWT Validation

For JWT (option 4):
```
JWT Validation Setup

JWKS URI (JSON Web Key Set endpoint):
Example: https://auth.example.com/.well-known/jwks.json

JWKS URI:
```

```
Token issuer (iss claim):
Example: https://auth.example.com

Issuer:
```

```
Expected audience (aud claim):
Example: mcp://my-server

Audience:
```

### 7. Authorization Rules

```
Do you want to add authorization rules to existing tools?

1. Yes - Review and configure tool access
2. No - I'll add authorization manually

Select (1-2):
```

If yes:
```
Found tools:
1. tool-name-1
2. tool-name-2
3. tool-name-3

Which tools should be restricted? (comma-separated numbers, or 'all'):
```

```
For tool "tool-name-1", who can access?
1. Admin only
2. Specific roles (specify)
3. Authenticated users only
4. Custom logic (I'll implement)

Select:
```

## Generated Code Examples

### API Key Authentication

```typescript
const server = new FastMCP({
  name: "{{serverName}}",
  version: "{{version}}",
  authenticate: (request) => {
    const apiKey = request.headers["{{headerName}}"];

    if (!apiKey) {
      throw new Response(null, {
        status: 401,
        statusText: "API key required",
      });
    }

    // Validate API key
    const validKey = process.env.API_KEY;
    if (apiKey !== validKey) {
      throw new Response(null, {
        status: 401,
        statusText: "Invalid API key",
      });
    }

    return { authenticated: true };
  },
});
```

### Role-Based Authentication

```typescript
// Define session type with roles
interface SessionData {
  userId: string;
  role: "admin" | "user" | "readonly";
}

const server = new FastMCP<SessionData>({
  name: "{{serverName}}",
  version: "{{version}}",
  authenticate: async (request) => {
    const apiKey = request.headers["x-api-key"];

    if (!apiKey) {
      throw new Response(null, {
        status: 401,
        statusText: "API key required",
      });
    }

    // Look up user by API key
    const user = await findUserByApiKey(apiKey);
    if (!user) {
      throw new Response(null, {
        status: 401,
        statusText: "Invalid API key",
      });
    }

    return {
      userId: user.id,
      role: user.role,
    };
  },
});

// Admin-only tool
server.addTool({
  name: "admin-dashboard",
  description: "Admin-only dashboard access",
  canAccess: (auth) => auth?.role === "admin",
  execute: async (args, { session }) => {
    return "Welcome admin " + session.userId;
  },
});

// Tool for admin and user roles
server.addTool({
  name: "edit-content",
  description: "Edit content",
  canAccess: (auth) => auth?.role === "admin" || auth?.role === "user",
  execute: async (args) => {
    return "Content edited";
  },
});

// Read-only accessible to all authenticated users
server.addTool({
  name: "view-content",
  description: "View content",
  execute: async (args) => {
    return "Content here";
  },
});
```

### OAuth with Google Provider

```typescript
import { FastMCP } from "fastmcp";
import { GoogleProvider } from "fastmcp/auth";

// Set up Google OAuth provider
const authProxy = new GoogleProvider({
  clientId: process.env.GOOGLE_CLIENT_ID!,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
  baseUrl: "{{baseUrl}}",
  scopes: [{{#each scopes}}"{{this}}"{{#unless @last}}, {{/unless}}{{/each}}],
});

interface SessionData {
  email: string;
  name: string;
}

const server = new FastMCP<SessionData>({
  name: "{{serverName}}",
  version: "{{version}}",
  oauth: {
    enabled: true,
    authorizationServer: authProxy.getAuthorizationServerMetadata(),
    proxy: authProxy,
  },
  authenticate: async (request) => {
    // OAuth tokens are validated by the proxy
    // Extract user info from the validated session
    const userInfo = await authProxy.getUserInfo(request);

    return {
      email: userInfo.email,
      name: userInfo.name,
    };
  },
});

// Access user info in tools
server.addTool({
  name: "whoami",
  description: "Get current user info",
  execute: async (args, { session }) => {
    return "Logged in as: " + session.name + " (" + session.email + ")";
  },
});
```

### JWT Validation

```typescript
import { FastMCP, DiscoveryDocumentCache } from "fastmcp";
import { buildGetJwks } from "get-jwks";
import fastJwt from "fast-jwt";

// Cache for OIDC discovery documents
const discoveryCache = new DiscoveryDocumentCache({
  ttl: 3600000, // 1 hour
});

interface SessionData {
  userId: string;
  email?: string;
  scope?: string;
}

const server = new FastMCP<SessionData>({
  name: "{{serverName}}",
  version: "{{version}}",
  oauth: {
    enabled: true,
    authorizationServer: {
      issuer: "{{issuer}}",
      authorizationEndpoint: "{{issuer}}/oauth/authorize",
      tokenEndpoint: "{{issuer}}/oauth/token",
      jwksUri: "{{jwksUri}}",
      responseTypesSupported: ["code"],
    },
    protectedResource: {
      resource: "{{audience}}",
      authorizationServers: ["{{issuer}}"],
    },
  },
  authenticate: async (request) => {
    const authHeader = request.headers.authorization;

    if (!authHeader?.startsWith("Bearer ")) {
      throw new Response(null, {
        status: 401,
        statusText: "Missing or invalid authorization header",
      });
    }

    const token = authHeader.slice(7);

    try {
      // Get JWKS for token validation
      const getJwks = buildGetJwks({
        jwksUrl: "{{jwksUri}}",
        cache: true,
        rateLimit: true,
      });

      // Create JWT verifier
      const verify = fastJwt.createVerifier({
        key: async (token) => {
          const { header } = fastJwt.decode(token, { complete: true });
          const jwk = await getJwks.getJwk({
            kid: header.kid,
            alg: header.alg,
          });
          return jwk;
        },
        algorithms: ["RS256", "ES256"],
        issuer: "{{issuer}}",
        audience: "{{audi

Related in AI Agents