#
tokens: 4394/50000 8/8 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .env.example
├── .gitignore
├── CLAUDE.md
├── EXAMPLES.md
├── LICENSE
├── package-lock.json
├── package.json
├── PACKAGING.md
├── README.md
└── server.js
```

# Files

--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------

```
# Perplexity API Key - Get yours at https://www.perplexity.ai/settings/api
PERPLEXITY_API_KEY=your_api_key_here

# Optional: Set DEBUG=1 for verbose logging
# DEBUG=1

```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Dependencies
node_modules/

# Environment
.env

# Logs
logs/
*.log

# Editor directories and files
.vscode/
.idea/
*.swp
*.swo

# OS specific files
.DS_Store
Thumbs.db

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Perplexity MCP Server

A custom [Model Context Protocol (MCP)](https://github.com/anthropics/model-context-protocol) implementation that adds Perplexity AI as a tool provider for Claude Desktop.

## Features

- Seamless integration with Claude Desktop through MCP
- Access to Perplexity's powerful AI models
- Support for both single questions and multi-turn conversations
- Customizable model selection

## Installation

### Prerequisites

- [Node.js](https://nodejs.org/) (v16 or higher)
- [Claude Desktop](https://claude.ai/desktop) (latest version)
- [Perplexity API key](https://www.perplexity.ai/settings/api)

### Option 1: Clone and Run Locally

1. Clone this repository:
   ```bash
   git clone https://github.com/Family-IT-Guy/perplexity-mcp.git
   cd perplexity-mcp
   ```

2. Install dependencies:
   ```bash
   npm install
   ```

3. Create a `.env` file with your API key:
   ```
   PERPLEXITY_API_KEY=your_api_key_here
   ```

4. Test the server:
   ```bash
   node server.js
   ```

### Option 2: Install Globally

1. Clone and navigate to the repository as above

2. Install globally:
   ```bash
   npm install -g .
   ```

3. Now you can run the server from anywhere:
   ```bash
   perplexity-mcp
   ```

## Claude Desktop Configuration

Add this configuration to your `claude_desktop_config.json` file:

### Standard Configuration
```json
{
  "mcpServers": {
    "perplexity": {
      "command": "node",
      "args": [
        "/absolute/path/to/perplexity-mcp/server.js"
      ],
      "env": {
        "PERPLEXITY_API_KEY": "your_perplexity_api_key"
      }
    }
  }
}
```

### Global Installation Configuration
```json
{
  "mcpServers": {
    "perplexity": {
      "command": "npx",
      "args": [
        "perplexity-mcp"
      ],
      "env": {
        "PERPLEXITY_API_KEY": "your_perplexity_api_key"
      }
    }
  }
}
```

### NVM Users
If you're using Node Version Manager (NVM), you need absolute paths:
```json
{
  "mcpServers": {
    "perplexity": {
      "command": "/Users/username/.nvm/versions/node/v16.x.x/bin/node",
      "args": [
        "/Users/username/path/to/perplexity-mcp/server.js"
      ],
      "env": {
        "PERPLEXITY_API_KEY": "your_perplexity_api_key"
      }
    }
  }
}
```

## Available Tools

Once configured, Claude will have access to these tools:

1. **perplexity_ask** - Send a single question to Perplexity
   - Parameters: 
     - `query` (required): The question to ask
     - `model` (optional): Model name (default: `llama-3.1-sonar-small-128k-online`)

2. **perplexity_chat** - Have a multi-turn conversation
   - Parameters:
     - `messages` (required): Array of conversation messages
     - `model` (optional): Model name (default: `mixtral-8x7b-instruct`)

## Troubleshooting

- Check logs: `cat ~/.claude/logs/perplexity.log`
- Ensure your API key is valid
- Verify your claude_desktop_config.json format
- Enable verbose logging by adding `"DEBUG": "1"` to the env section

## How It Works

This implementation uses the Model Context Protocol (MCP) created by Anthropic to extend Claude Desktop's capabilities. It:

1. Creates an MCP server that communicates with Claude via stdio
2. Registers Perplexity tools with Claude
3. Proxies requests from Claude to the Perplexity API
4. Returns responses back to Claude for display

## License

This project is licensed under the ISC License - see the LICENSE file for details.

```

--------------------------------------------------------------------------------
/CLAUDE.md:
--------------------------------------------------------------------------------

```markdown
# Perplexity MCP Server Guide

## Quick Start
1. **Install Dependencies**: `npm install`
2. **Set API Key**: Add to `.env` file or use environment variable:
   ```
   PERPLEXITY_API_KEY=your_api_key_here
   ```
3. **Run Server**: `node server.js`

## Claude Desktop Configuration
Add to `claude_desktop_config.json`:
```json
{
  "mcpServers": {
    "perplexity": {
      "command": "node",
      "args": [
        "/absolute/path/to/perplexity-mcp/server.js"
      ],
      "env": {
        "PERPLEXITY_API_KEY": "your_perplexity_api_key"
      }
    }
  }
}
```

## NPM Global Installation
Run: `npm install -g .`

Then configure in Claude Desktop:
```json
{
  "mcpServers": {
    "perplexity": {
      "command": "npx",
      "args": [
        "perplexity-mcp"
      ],
      "env": {
        "PERPLEXITY_API_KEY": "your_perplexity_api_key"
      }
    }
  }
}
```

## NVM Users
If using NVM, you must use absolute paths to both node and the script:
```json
{
  "mcpServers": {
    "perplexity": {
      "command": "/Users/username/.nvm/versions/node/v16.x.x/bin/node",
      "args": [
        "/Users/username/path/to/perplexity-mcp/server.js"
      ],
      "env": {
        "PERPLEXITY_API_KEY": "your_perplexity_api_key"
      }
    }
  }
}
```

## Available Tools
- **perplexity_ask**: Send a single question to Perplexity
  - Default model: `llama-3.1-sonar-small-128k-online`
- **perplexity_chat**: Multi-turn conversation with Perplexity 
  - Default model: `mixtral-8x7b-instruct`

## Troubleshooting
- Check logs with `cat ~/.claude/logs/perplexity.log`
- Ensure your API key is valid and has not expired
- Validate your claude_desktop_config.json format
- Add verbose logging with the `DEBUG=1` environment variable

## Architecture
- Built with the MCP protocol
- Communication via stdio transport
- Lightweight proxy to Perplexity API
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "perplexity-mcp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "bin": {
    "perplexity-mcp": "./server.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.7.0",
    "dotenv": "^16.4.7",
    "isomorphic-fetch": "^3.0.0"
  }
}
```

--------------------------------------------------------------------------------
/PACKAGING.md:
--------------------------------------------------------------------------------

```markdown
# Packaging Guide for Contributors

This document explains how to package and distribute the Perplexity MCP server to others.

## Creating a Distribution Package

### 1. Clean Up the Project

Remove unnecessary files:
- Remove any personal configuration files
- Delete the `.env` file if it contains your API key
- Clean up the `node_modules` directory (it will be reinstalled by users)

### 2. Package the Project

#### Option A: GitHub Repository

1. Create a GitHub repository and push your code:
   ```bash
   git init
   git add .
   git commit -m "Initial commit"
   git remote add origin https://github.com/Family-IT-Guy/perplexity-mcp.git
   git push -u origin main
   ```

2. In your README.md, provide clone instructions pointing to your repository.

#### Option B: Create a ZIP file

1. Clean the project:
   ```bash
   rm -rf node_modules
   rm -f .env
   ```

2. Create a ZIP archive:
   ```bash
   zip -r perplexity-mcp.zip .
   ```

3. Share this ZIP file with users.

#### Option C: Publish to npm (advanced)

1. Update package.json with appropriate metadata
2. Publish the package:
   ```bash
   npm publish
   ```

## Distribution Checklist

Ensure your package includes:

- [ ] README.md with installation and usage instructions
- [ ] server.js - the main MCP server implementation
- [ ] package.json with correct dependencies
- [ ] CLAUDE.md with detailed configuration instructions
- [ ] Example .env file (without real API keys)
- [ ] License file

## User Setup Instructions

Provide these instructions to your users:

1. Install Node.js (v16 or higher)
2. Get a Perplexity API key from https://www.perplexity.ai/settings/api
3. Install your package using one of these methods:
   - Git clone (if hosted on GitHub)
   - Download and extract ZIP
   - npm install (if published)
4. Run `npm install` to install dependencies
5. Create a `.env` file with their API key
6. Configure Claude Desktop (refer to README.md or CLAUDE.md for details)
7. Test the implementation with Claude Desktop

## Common Issues

Prepare users for these common issues:

1. **API Key Problems**
   - Remind users to keep their API key secure
   - API keys might have rate limits or usage quotas

2. **Node.js Version Issues**
   - Users should check their Node.js version with `node -v`
   - If using NVM, they need absolute paths as described in CLAUDE.md

3. **Permission Problems**
   - Server.js needs executable permission: `chmod +x server.js`

4. **Claude Desktop Configuration**
   - Common configuration issues include missing absolute paths
   - JSON syntax errors in the config file

5. **Error Logs**
   - Instruct users how to check logs: `cat ~/.claude/logs/perplexity.log`
   - Explain how to interpret common error messages

```

--------------------------------------------------------------------------------
/EXAMPLES.md:
--------------------------------------------------------------------------------

```markdown
# Usage Examples

This document provides examples of how to use the Perplexity MCP tools with Claude Desktop.

## perplexity_ask

The `perplexity_ask` tool allows you to send a single question to Perplexity AI and get a response.

### Basic Example

In Claude Desktop, try prompts like:

```
Please use Perplexity to answer: What is the current population of Tokyo?
```

Claude will respond with something like:

```
I'll use Perplexity to look that up for you.

According to Perplexity, the current population of Tokyo is approximately 14 million in the city proper, while the greater Tokyo metropolitan area has around 37 million inhabitants, making it the most populous metropolitan area in the world.
```

### With Custom Model

You can specify a different model:

```
Please use Perplexity with the model "llama-3.1-8b-instant" to answer: What are the main features of TypeScript?
```

## perplexity_chat

The `perplexity_chat` tool allows for multi-turn conversations with Perplexity AI.

### Basic Conversation

Ask Claude to start a conversation with Perplexity:

```
Please use Perplexity to have a 3-turn conversation about quantum computing. 
First, ask what quantum computing is. 
Then ask about quantum supremacy. 
Finally, ask about practical applications today.
```

Claude will use the chat API to maintain context across multiple turns.

### With System Prompt

For more control over the conversation, you can have Claude use a system prompt:

```
Please use Perplexity chat with a system prompt instructing it to explain concepts to a high school student, and then ask about nuclear fusion.
```

Claude might construct a messages array like:
```json
[
  {
    "role": "system",
    "content": "You are an educational assistant explaining complex topics to high school students. Use simple language and relevant analogies."
  },
  {
    "role": "user",
    "content": "What is nuclear fusion and how does it work?"
  }
]
```

## Advanced Usage

### Combining with Other Claude Capabilities

You can have Claude process or analyze Perplexity's responses:

```
Please use Perplexity to research the latest developments in renewable energy, then create a summary table of the key points.
```

### Comparing Different Models

You can compare responses from different models:

```
Please use Perplexity to answer "What is the future of artificial intelligence?" twice - once with the default model and once with "llama-3.1-70b-versatile". Then compare and contrast the responses.
```

## Tips for Best Results

1. **Be specific in your queries** - The more specific your request, the better the response.

2. **Use appropriate models** for your needs:
   - `llama-3.1-sonar-small-128k-online` - Great for factual questions requiring web search
   - `mixtral-8x7b-instruct` - Good for general-purpose chat
   - `llama-3.1-70b-versatile` - Stronger reasoning capabilities
   - `llama-3.1-8b-instant` - Faster responses

3. **For complex topics**, breaking down into multiple questions often yields better results than a single complex query.

4. **For web research**, the `perplexity_ask` tool with the default model generally works best as it includes online search capability.
```

--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node
// Simple Perplexity MCP Server
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import dotenv from 'dotenv';
import fetch from 'isomorphic-fetch';

console.error("Starting Perplexity MCP Server...");

// Load API key from .env file or environment
dotenv.config();
const API_KEY = process.env.PERPLEXITY_API_KEY;

if (!API_KEY) {
  console.error('Error: PERPLEXITY_API_KEY environment variable is required');
  process.exit(1);
}

console.error("API key found, initializing server...");

// Create MCP server
const server = new Server({
  name: "perplexity-mcp-server",
  version: "0.1.0"
}, {
  capabilities: {
    tools: {}
  }
});

// Define tools
const tools = [
  {
    name: 'perplexity_ask',
    description: 'Send a simple query to Perplexity AI',
    inputSchema: {
      type: 'object',
      properties: {
        query: { type: 'string', description: 'The question to ask' },
        model: { type: 'string', description: 'Optional model name' }
      },
      required: ['query']
    }
  },
  {
    name: 'perplexity_chat',
    description: 'Have a multi-turn conversation with Perplexity AI',
    inputSchema: {
      type: 'object',
      properties: {
        messages: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              role: { type: 'string', enum: ['system', 'user', 'assistant'] },
              content: { type: 'string' }
            }
          }
        },
        model: { type: 'string', description: 'Optional model name' }
      },
      required: ['messages']
    }
  }
];

// List available tools
console.error("Setting up listTools handler...");
server.setRequestHandler(
  ListToolsRequestSchema, 
  async () => {
    console.error("Listing tools...");
    return {
      tools: tools.map(({ name, description, inputSchema }) => ({
        name, description, inputSchema
      }))
    };
  }
);

// Handle tool calls
console.error("Setting up callTool handler...");
server.setRequestHandler(
  CallToolRequestSchema,
  async (request) => {
    console.error(`Got tool call request: ${JSON.stringify(request.params)}`);
    try {
      const { name, arguments: args } = request.params;
      
      if (name === 'perplexity_ask') {
        console.error(`Running perplexity_ask with query: ${args.query}`);
        const messages = [{ role: 'user', content: args.query }];
        const model = args.model || 'llama-3.1-sonar-small-128k-online';
        
        const response = await fetch('https://api.perplexity.ai/chat/completions', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': `Bearer ${API_KEY}`
          },
          body: JSON.stringify({ model, messages })
        });
        
        if (!response.ok) {
          throw new Error(`API error: ${response.status}`);
        }
        
        const data = await response.json();
        console.error("Got response from Perplexity API");
        return {
          content: [{ 
            type: 'text', 
            text: data.choices[0].message.content 
          }]
        };
      }
      
      else if (name === 'perplexity_chat') {
        console.error(`Running perplexity_chat with ${args.messages?.length || 0} messages`);
        const model = args.model || 'mixtral-8x7b-instruct';
        
        const response = await fetch('https://api.perplexity.ai/chat/completions', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': `Bearer ${API_KEY}`
          },
          body: JSON.stringify({ 
            model, 
            messages: args.messages 
          })
        });
        
        if (!response.ok) {
          throw new Error(`API error: ${response.status}`);
        }
        
        const data = await response.json();
        console.error("Got response from Perplexity API");
        return {
          content: [{ 
            type: 'text', 
            text: data.choices[0].message.content 
          }]
        };
      }
      
      else {
        console.error(`Unknown tool: ${name}`);
        return {
          content: [{ type: 'text', text: `Unknown tool: ${name}` }],
          isError: true
        };
      }
    } 
    catch (error) {
      console.error(`Error in tool call: ${error.message}`);
      return {
        content: [{ 
          type: 'text', 
          text: `Error: ${error.message}` 
        }],
        isError: true
      };
    }
  }
);

// Set up error handling
server.onerror = (error) => {
  console.error("[Error]", error);
};

// Start the server
console.error("Connecting server transport...");
const transport = new StdioServerTransport();
server.connect(transport).catch(error => {
  console.error("Failed to connect transport:", error);
});
console.error("Perplexity MCP Server running...");
```