Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'

- name: Bootstrap
run: ./scripts/bootstrap
Expand All @@ -46,7 +46,7 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'

- name: Bootstrap
run: ./scripts/bootstrap
Expand All @@ -68,6 +68,15 @@ jobs:
AUTH: ${{ steps.github-oidc.outputs.github_token }}
SHA: ${{ github.sha }}
run: ./scripts/utils/upload-artifact.sh

- name: Upload MCP Server tarball
if: github.repository == 'stainless-sdks/perplexity-typescript'
env:
URL: https://pkg.stainless.com/s?subpackage=mcp-server
AUTH: ${{ steps.github-oidc.outputs.github_token }}
SHA: ${{ github.sha }}
BASE_PATH: packages/mcp-server
run: ./scripts/utils/upload-artifact.sh
test:
timeout-minutes: 10
name: test
Expand All @@ -79,10 +88,13 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'

- name: Bootstrap
run: ./scripts/bootstrap

- name: Build
run: ./scripts/build

- name: Run tests
run: ./scripts/test
103 changes: 103 additions & 0 deletions .github/workflows/docker-mcp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Build and Push MCP Server Docker Image

# This workflow is triggered when a GitHub release is created.
# It can also be run manually to re-publish to Docker Hub in case it failed for some reason.
# You can run this workflow by navigating to https://www.github.com/perplexityai/perplexity-node/actions/workflows/docker-mcp.yml
on:
release:
types: [published]

workflow_dispatch:

env:
REGISTRY: docker.io
IMAGE_NAME: perplexityai/perplexity-mcp

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# For OIDC token if using Docker Hub provenance
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
image=moby/buildkit:latest

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Determine Docker tags
id: tags
run: |
# Get tags from our script
TAGS=$(bash ./bin/docker-tags)

# Convert to format expected by docker/metadata-action
DOCKER_TAGS=""
while IFS= read -r tag; do
if [ -n "$DOCKER_TAGS" ]; then
DOCKER_TAGS="${DOCKER_TAGS}\n"
fi
DOCKER_TAGS="${DOCKER_TAGS}type=raw,value=${tag}"
done <<< "$TAGS"

# Output for docker/metadata-action
echo "tags<<EOF" >> $GITHUB_OUTPUT
echo -e "$DOCKER_TAGS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Save for build summary
echo "DOCKER_TAG_LIST<<EOF" >> $GITHUB_ENV
echo "$TAGS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
${{ steps.tags.outputs.tags }}
labels: |
org.opencontainers.image.title=Perplexity MCP Server
org.opencontainers.image.description=Model Context Protocol server for Perplexity API
org.opencontainers.image.vendor=perplexity

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ./packages/mcp-server/Dockerfile
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: true
sbom: true

- name: Generate build summary
run: |
echo "## Docker Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Tags:**" >> $GITHUB_STEP_SUMMARY
echo "$DOCKER_TAG_LIST" | sed 's/^/- `/' | sed 's/$/`/' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Platforms:** linux/amd64" >> $GITHUB_STEP_SUMMARY
20 changes: 19 additions & 1 deletion .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
name: Publish NPM
on:
workflow_dispatch:
inputs:
path:
description: The path to run the release in, e.g. '.' or 'packages/mcp-server'
required: true

release:
types: [published]
Expand All @@ -12,6 +16,8 @@ jobs:
publish:
name: publish
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@v4
Expand All @@ -27,6 +33,18 @@ jobs:

- name: Publish to NPM
run: |
bash ./bin/publish-npm
if [ -n "${{ github.event.inputs.path }}" ]; then
PATHS_RELEASED='[\"${{ github.event.inputs.path }}\"]'
else
PATHS_RELEASED='[\".\", \"packages/mcp-server\"]'
fi
yarn tsn scripts/publish-packages.ts "{ \"paths_released\": \"$PATHS_RELEASED\" }"
env:
NPM_TOKEN: ${{ secrets.PERPLEXITY_NPM_TOKEN || secrets.NPM_TOKEN }}

- name: Upload MCP Server DXT GitHub release asset
run: |
gh release upload ${{ github.event.release.tag_name }} \
packages/mcp-server/perplexity_ai_perplexity_ai_api.mcpb
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .github/workflows/release-doctor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ jobs:
bash ./bin/check-release-environment
env:
NPM_TOKEN: ${{ secrets.PERPLEXITY_NPM_TOKEN || secrets.NPM_TOKEN }}
DOCKERHUB_TOKEN: ${{ secrets.PERPLEXITY_DOCKERHUB_TOKEN || secrets.DOCKERHUB_TOKEN }}

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ dist-deno
/*.tgz
.idea/
.eslintcache

dist-bundle
*.mcpb
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ CHANGELOG.md
/deno

# don't format tsc output, will break source maps
/dist
dist
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.12.0"
".": "0.13.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 5
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai%2Fperplexity-cf9f981e30f8c9739f337a8b20436cebdbf35fffc70d6db5a09ec5a3b68cddef.yml
openapi_spec_hash: d0cdcfdde0a0046e6451305475060748
config_hash: 29552caca3e91432ed1a14f4a38487cc
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai%2Fperplexity-335f0ceddae39ba77e5abf8b2b72691a43174b25c2ec897cd7779db8d1524820.yml
openapi_spec_hash: e34fc7a3c97b61c7aded4df4774f298e
config_hash: 4e2c5b7ad4caa07a2ac1af091ecf6c9c
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 0.13.0 (2025-10-29)

Full Changelog: [v0.12.0...v0.13.0](https://github.com/perplexityai/perplexity-node/compare/v0.12.0...v0.13.0)

### Features

* **api:** manual updates ([ab3c07b](https://github.com/perplexityai/perplexity-node/commit/ab3c07b646009f43ac4d0001e6d61e8562073aba))


### Chores

* configure new SDK language ([3cbc5a5](https://github.com/perplexityai/perplexity-node/commit/3cbc5a5e922e5fe0b2092b0088145bc1103f87d5))

## 0.12.0 (2025-10-16)

Full Changelog: [v0.11.0...v0.12.0](https://github.com/perplexityai/perplexity-node/compare/v0.11.0...v0.12.0)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,12 @@ await client.chat.completions.create({ messages: [{ role: 'user', content: 'What

### Timeouts

Requests time out after 1 minute by default. You can configure this with a `timeout` option:
Requests time out after 15 minutes by default. You can configure this with a `timeout` option:

```ts
// Configure the default for all requests:
const client = new Perplexity({
timeout: 20 * 1000, // 20 seconds (default is 1 minute)
timeout: 20 * 1000, // 20 seconds (default is 15 minutes)
});

// Override per-request:
Expand Down
20 changes: 10 additions & 10 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ Methods:

- <code title="post /chat/completions">client.chat.completions.<a href="./src/resources/chat/completions.ts">create</a>({ ...params }) -> StreamChunk</code>

# Search

Types:

- <code><a href="./src/resources/search.ts">SearchCreateResponse</a></code>

Methods:

- <code title="post /search">client.search.<a href="./src/resources/search.ts">create</a>({ ...params }) -> SearchCreateResponse</code>

# Async

## Chat
Expand All @@ -37,13 +47,3 @@ Methods:
- <code title="post /async/chat/completions">client.async.chat.completions.<a href="./src/resources/async/chat/completions.ts">create</a>({ ...params }) -> CompletionCreateResponse</code>
- <code title="get /async/chat/completions">client.async.chat.completions.<a href="./src/resources/async/chat/completions.ts">list</a>() -> CompletionListResponse</code>
- <code title="get /async/chat/completions/{api_request}">client.async.chat.completions.<a href="./src/resources/async/chat/completions.ts">get</a>(apiRequest, { ...params }) -> CompletionGetResponse</code>

# Search

Types:

- <code><a href="./src/resources/search.ts">SearchCreateResponse</a></code>

Methods:

- <code title="post /search">client.search.<a href="./src/resources/search.ts">create</a>({ ...params }) -> SearchCreateResponse</code>
4 changes: 4 additions & 0 deletions bin/check-release-environment
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ if [ -z "${NPM_TOKEN}" ]; then
errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets")
fi

if [ -z "${DOCKERHUB_TOKEN}" ]; then
errors+=("The DOCKERHUB_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets")
fi

lenErrors=${#errors[@]}

if [[ lenErrors -gt 0 ]]; then
Expand Down
88 changes: 88 additions & 0 deletions bin/docker-tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env bash

set -euo pipefail

# This script determines which Docker tags to use based on the version
# It outputs a newline-separated list of tags

# Get version from mcp-server package.json
if [ -f "packages/mcp-server/package.json" ]; then
VERSION="$(jq -r -e '.version' ./packages/mcp-server/package.json)"
else
echo "ERROR: Could not determine version from packages/mcp-server/package.json" >&2
exit 1
fi

# Check if current version is pre-release (e.g. alpha / beta / rc)
CURRENT_IS_PRERELEASE=false
PRERELEASE_TAG=""
if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then
CURRENT_IS_PRERELEASE=true
PRERELEASE_TAG="${BASH_REMATCH[1]}"
fi

# Check if there's any stable release in Docker Hub
# This matches the npm logic: check if ANY stable version exists
DOCKER_IMAGE="${DOCKER_IMAGE:-perplexityai/perplexity-mcp}"
HAS_STABLE_RELEASE=false

PAGE=1
PAGE_SIZE=100

while true; do
RESPONSE=$(curl -s --max-time 30 "https://hub.docker.com/v2/repositories/${DOCKER_IMAGE}/tags?page=${PAGE}&page_size=${PAGE_SIZE}")

if [ $? -ne 0 ]; then
echo "ERROR: Failed to fetch tags from Docker Hub" >&2
exit 1
fi

# Check for 404 error - repository doesn't exist yet
if echo "$RESPONSE" | jq -e '.message == "httperror 404: object not found"' >/dev/null 2>&1; then
# Repository doesn't exist, no stable releases
HAS_STABLE_RELEASE=false
break
fi

if ! echo "$RESPONSE" | jq -e '.results' >/dev/null 2>&1; then
echo "ERROR: Invalid JSON response from Docker Hub" >&2
echo "Response: $RESPONSE" >&2
exit 1
fi

# Check if any tags are stable versions (no pre-release suffix)
STABLE_TAGS=$(echo "$RESPONSE" | jq -r '.results[].name | select(test("^[0-9]+\\.[0-9]+\\.[0-9]+$"))' 2>/dev/null || true)
if [ -n "$STABLE_TAGS" ]; then
HAS_STABLE_RELEASE=true
break
fi

NEXT_URL=$(echo "$RESPONSE" | jq -r '.next // empty')
if [ -z "$NEXT_URL" ]; then
break
fi

PAGE=$((PAGE + 1))
done

# Output tags based on the logic (matching npm):
# 1. Always output the exact version tag
echo "$VERSION"

# 2. Use pre-release tag (alpha/beta) if there's already a stable release and we're publishing a pre-release
# Otherwise use 'latest'
if $CURRENT_IS_PRERELEASE && $HAS_STABLE_RELEASE; then
# Only tag with pre-release type, not latest
echo "$PRERELEASE_TAG"
else
# Tag as latest (either it's a stable release, or it's a pre-release but no stable exists yet)
echo "latest"

# For stable releases, also add major and major.minor tags
if ! $CURRENT_IS_PRERELEASE && [[ "$VERSION" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
MAJOR="${BASH_REMATCH[1]}"
MINOR="${BASH_REMATCH[2]}"
echo "$MAJOR"
echo "$MAJOR.$MINOR"
fi
fi
2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default tseslint.config(
},
},
{
files: ['tests/**', 'examples/**'],
files: ['tests/**', 'examples/**', 'packages/**'],
rules: {
'no-restricted-imports': 'off',
},
Expand Down
Loading
Loading