Skip to main content

Overview

Integrate Civic Nexus with Anthropic’s Messages API using the native MCP connector feature. This is built directly into the API - no separate MCP client needed!
Native MCP Support: The Anthropic Messages API includes built-in MCP connector support. Just add the mcp_servers parameter to your API calls.

Prerequisites

Prerequisites:
  1. Node.js 18+ project (Next.js 14+ or any Node.js framework)
  2. Civic account - Create account
  3. Connect services at nexus.civic.com (GitHub, Slack, etc.)
  4. Anthropic API Key - Get yours at console.anthropic.com
  5. Complete Civic Auth setup (see Access Token Setup below)

Access Token Setup (Next.js + Civic Auth)

Why Civic Auth? Nexus needs to identify which user is accessing tools and authorize their permissions. Civic Auth provides the secure access token. (Support for additional identity providers coming soon.)
  • 1. next.config.ts
  • 2. API Route
  • 3. Middleware
  • 4. Get Token
import { createCivicAuthPlugin } from "@civic/auth/nextjs"
import type { NextConfig } from "next";

const nextConfig: NextConfig = {};
const withCivicAuth = createCivicAuthPlugin({ clientId: "YOUR_CLIENT_ID" });
export default withCivicAuth(nextConfig)
Get your Client ID at auth.civic.com
Non-Next.js: Forward a Bearer token from your frontend or validate incoming tokens server-side (see /libraries/auth-verify).

Environment Variables

Create a .env.local file in your project root:
# Get your Client ID at https://auth.civic.com
CIVIC_AUTH_CLIENT_ID=your_client_id_here

# Anthropic API key
ANTHROPIC_API_KEY=your_anthropic_api_key
Getting your Civic Client ID:
  1. Visit auth.civic.com
  2. Create a new application or use an existing one
  3. Copy the Client ID from your application settings

Installation

Install the required packages:
npm install @anthropic-ai/sdk
Note: No MCP SDK required! The MCP connector is built into the Anthropic SDK.

Basic Setup

Create Message with MCP Connector

import Anthropic from '@anthropic-ai/sdk';
import { getTokens } from '@civic/auth/nextjs';

async function createMessage(userMessage: string) {
  const { accessToken } = await getTokens();

  if (!accessToken) {
    throw new Error('No access token available. User must be authenticated.');
  }

  const client = new Anthropic({
    apiKey: process.env.ANTHROPIC_API_KEY!,
  });

  const response = await client.messages.create({
    model: 'claude-sonnet-4-5',
    max_tokens: 1024,
    messages: [{ role: 'user', content: userMessage }],
    mcp_servers: [
      {
        type: 'url',
        url: 'https://nexus.civic.com/hub/mcp',
        name: 'civic-nexus',
        authorization_token: accessToken,
      },
    ],
  }, {
    headers: {
      'anthropic-beta': 'mcp-client-2025-04-04',
    },
  });

  return response;
}
Key Points:
  • Add mcp_servers parameter to your messages.create() call
  • Include the beta header: "anthropic-beta": "mcp-client-2025-04-04"
  • Pass your Civic access token as authorization_token
  • That’s it! No tool looping, no MCP client setup

Complete Example: Next.js API Route

// app/api/chat/route.ts
import { NextRequest, NextResponse } from 'next/server';
import Anthropic from '@anthropic-ai/sdk';
import { getTokens } from '@civic/auth/nextjs';

export async function POST(req: NextRequest) {
  try {
    const { messages } = await req.json();

    if (!messages || !Array.isArray(messages)) {
      return NextResponse.json(
        { error: 'Invalid request: messages array required' },
        { status: 400 }
      );
    }

    const { accessToken } = await getTokens();

    if (!accessToken) {
      return NextResponse.json(
        { error: 'Not authenticated' },
        { status: 401 }
      );
    }

    const client = new Anthropic({
      apiKey: process.env.ANTHROPIC_API_KEY!,
    });

    const response = await client.messages.create({
      model: 'claude-sonnet-4-5',
      max_tokens: 4096,
      messages,
      mcp_servers: [
        {
          type: 'url',
          url: 'https://nexus.civic.com/hub/mcp',
          name: 'civic-nexus',
          authorization_token: accessToken,
        },
      ],
    }, {
      headers: {
        'anthropic-beta': 'mcp-client-2025-04-04',
      },
    });

    return NextResponse.json(response);
  } catch (error) {
    console.error('Anthropic API error:', error);
    const errorMessage = error instanceof Error ? error.message : 'Failed to process request';
    const statusCode = errorMessage.includes('authentication') ? 401 : 500;

    return NextResponse.json(
      { error: errorMessage },
      { status: statusCode }
    );
  }
}

Streaming Responses

For real-time streaming:
const stream = await client.messages.create({
  model: 'claude-sonnet-4-5',
  max_tokens: 4096,
  messages: [{ role: 'user', content: 'List my GitHub repositories' }],
  mcp_servers: [
    {
      type: 'url',
      url: 'https://nexus.civic.com/hub/mcp',
      name: 'civic-nexus',
      authorization_token: accessToken,
    },
  ],
  stream: true,
}, {
  headers: {
    'anthropic-beta': 'mcp-client-2025-04-04',
  },
});

for await (const event of stream) {
  if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
    console.log(event.delta.text);
  }
}

Tool Configuration (Optional)

Restrict which tools Claude can use:
mcp_servers: [
  {
    type: 'url',
    url: 'https://nexus.civic.com/hub/mcp',
    name: 'civic-nexus',
    authorization_token: accessToken,
    tool_configuration: {
      enabled: true,
      allowed_tools: ['github__list_repos', 'slack__search_messages']
    }
  },
]

Key Advantages

Native Integration

Built directly into Messages API - no extra SDKs

Automatic Tools

Claude discovers and calls tools automatically

Simple Setup

Just add mcp_servers parameter to API calls

Streaming Support

Real-time responses with stream: true

Nexus Authentication

mcp_servers: [
  {
    type: 'url',
    url: 'https://nexus.civic.com/hub/mcp',
    name: 'civic-nexus',
    authorization_token: accessToken, // Civic access token
  },
]
headers: {
  'anthropic-beta': 'mcp-client-2025-04-04',
}
import { getTokens } from "@civic/auth/nextjs";
const { accessToken } = await getTokens();

Response Format

Claude returns mcp_tool_use blocks in the response:
{
  "type": "mcp_tool_use",
  "id": "mcptoolu_01234...",
  "name": "github__list_repos",
  "input": {
    "owner": "username"
  }
}
These are handled automatically by Claude - you don’t need to process them manually.

Current Limitations

The MCP connector currently only supports:
  • Tool calls (not MCP resources or prompts)
  • HTTP servers (not STDIO servers)
  • SSE and Streamable HTTP transports
Amazon Bedrock and Google Vertex integrations are not yet supported.

Comparison with Other Approaches

FeatureAnthropic MCP ConnectorOpenAI Agents SDKVercel AI SDK
Setup ComplexityLowLowMedium
MCP SDK NeededNoNoYes
Tool LoopingNo (automatic)No (automatic)Yes (manual)
Best ForDirect API usageQuick prototypesNext.js apps
StreamingYesYesYes

Next Steps

1

Test with Simple Queries

Try “list my GitHub repos” or “search Slack messages about X”
2

Connect More Services

Visit nexus.civic.com to connect additional tools
3

Configure Tool Access

Use tool_configuration to restrict which tools Claude can use
4

Deploy

Deploy your application to production
I