Skip to content

Commit ab3c07b

Browse files
feat(api): manual updates
1 parent 3cbc5a5 commit ab3c07b

30 files changed

+358
-1356
lines changed

.github/workflows/docker-mcp.yml

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: Build and Push MCP Server Docker Image
2+
3+
# This workflow is triggered when a GitHub release is created.
4+
# It can also be run manually to re-publish to Docker Hub in case it failed for some reason.
5+
# You can run this workflow by navigating to https://www.github.com/perplexityai/perplexity-node/actions/workflows/docker-mcp.yml
6+
on:
7+
release:
8+
types: [published]
9+
10+
workflow_dispatch:
11+
12+
env:
13+
REGISTRY: docker.io
14+
IMAGE_NAME: perplexityai/perplexity-mcp
15+
16+
jobs:
17+
build-and-push:
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
packages: write
22+
# For OIDC token if using Docker Hub provenance
23+
id-token: write
24+
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
29+
- name: Set up Docker Buildx
30+
uses: docker/setup-buildx-action@v3
31+
with:
32+
driver-opts: |
33+
image=moby/buildkit:latest
34+
35+
- name: Log in to Docker Hub
36+
uses: docker/login-action@v3
37+
with:
38+
registry: ${{ env.REGISTRY }}
39+
username: ${{ vars.DOCKERHUB_USERNAME }}
40+
password: ${{ secrets.DOCKERHUB_TOKEN }}
41+
42+
- name: Determine Docker tags
43+
id: tags
44+
run: |
45+
# Get tags from our script
46+
TAGS=$(bash ./bin/docker-tags)
47+
48+
# Convert to format expected by docker/metadata-action
49+
DOCKER_TAGS=""
50+
while IFS= read -r tag; do
51+
if [ -n "$DOCKER_TAGS" ]; then
52+
DOCKER_TAGS="${DOCKER_TAGS}\n"
53+
fi
54+
DOCKER_TAGS="${DOCKER_TAGS}type=raw,value=${tag}"
55+
done <<< "$TAGS"
56+
57+
# Output for docker/metadata-action
58+
echo "tags<<EOF" >> $GITHUB_OUTPUT
59+
echo -e "$DOCKER_TAGS" >> $GITHUB_OUTPUT
60+
echo "EOF" >> $GITHUB_OUTPUT
61+
62+
# Save for build summary
63+
echo "DOCKER_TAG_LIST<<EOF" >> $GITHUB_ENV
64+
echo "$TAGS" >> $GITHUB_ENV
65+
echo "EOF" >> $GITHUB_ENV
66+
67+
- name: Extract metadata
68+
id: meta
69+
uses: docker/metadata-action@v5
70+
with:
71+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
72+
tags: |
73+
${{ steps.tags.outputs.tags }}
74+
labels: |
75+
org.opencontainers.image.title=Perplexity MCP Server
76+
org.opencontainers.image.description=Model Context Protocol server for Perplexity API
77+
org.opencontainers.image.vendor=perplexity
78+
79+
- name: Build and push Docker image
80+
uses: docker/build-push-action@v6
81+
with:
82+
context: .
83+
file: ./packages/mcp-server/Dockerfile
84+
platforms: linux/amd64
85+
push: true
86+
tags: ${{ steps.meta.outputs.tags }}
87+
labels: ${{ steps.meta.outputs.labels }}
88+
annotations: ${{ steps.meta.outputs.annotations }}
89+
cache-from: type=gha
90+
cache-to: type=gha,mode=max
91+
provenance: true
92+
sbom: true
93+
94+
- name: Generate build summary
95+
run: |
96+
echo "## Docker Build Summary" >> $GITHUB_STEP_SUMMARY
97+
echo "" >> $GITHUB_STEP_SUMMARY
98+
echo "**Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY
99+
echo "" >> $GITHUB_STEP_SUMMARY
100+
echo "**Tags:**" >> $GITHUB_STEP_SUMMARY
101+
echo "$DOCKER_TAG_LIST" | sed 's/^/- `/' | sed 's/$/`/' >> $GITHUB_STEP_SUMMARY
102+
echo "" >> $GITHUB_STEP_SUMMARY
103+
echo "**Platforms:** linux/amd64" >> $GITHUB_STEP_SUMMARY

.github/workflows/release-doctor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ jobs:
1919
bash ./bin/check-release-environment
2020
env:
2121
NPM_TOKEN: ${{ secrets.PERPLEXITY_NPM_TOKEN || secrets.NPM_TOKEN }}
22+
DOCKERHUB_TOKEN: ${{ secrets.PERPLEXITY_DOCKERHUB_TOKEN || secrets.DOCKERHUB_TOKEN }}
2223

.stats.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 5
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai%2Fperplexity-cf9f981e30f8c9739f337a8b20436cebdbf35fffc70d6db5a09ec5a3b68cddef.yml
3-
openapi_spec_hash: d0cdcfdde0a0046e6451305475060748
4-
config_hash: 990b8c6efa583874f556a845bc9b6e00
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai%2Fperplexity-335f0ceddae39ba77e5abf8b2b72691a43174b25c2ec897cd7779db8d1524820.yml
3+
openapi_spec_hash: e34fc7a3c97b61c7aded4df4774f298e
4+
config_hash: 4e2c5b7ad4caa07a2ac1af091ecf6c9c

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,12 @@ await client.chat.completions.create({ messages: [{ role: 'user', content: 'What
269269

270270
### Timeouts
271271

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

274274
```ts
275275
// Configure the default for all requests:
276276
const client = new Perplexity({
277-
timeout: 20 * 1000, // 20 seconds (default is 1 minute)
277+
timeout: 20 * 1000, // 20 seconds (default is 15 minutes)
278278
});
279279

280280
// Override per-request:

api.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ Methods:
2020

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

23+
# Search
24+
25+
Types:
26+
27+
- <code><a href="./src/resources/search.ts">SearchCreateResponse</a></code>
28+
29+
Methods:
30+
31+
- <code title="post /search">client.search.<a href="./src/resources/search.ts">create</a>({ ...params }) -> SearchCreateResponse</code>
32+
2333
# Async
2434

2535
## Chat
@@ -37,13 +47,3 @@ Methods:
3747
- <code title="post /async/chat/completions">client.async.chat.completions.<a href="./src/resources/async/chat/completions.ts">create</a>({ ...params }) -> CompletionCreateResponse</code>
3848
- <code title="get /async/chat/completions">client.async.chat.completions.<a href="./src/resources/async/chat/completions.ts">list</a>() -> CompletionListResponse</code>
3949
- <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>
40-
41-
# Search
42-
43-
Types:
44-
45-
- <code><a href="./src/resources/search.ts">SearchCreateResponse</a></code>
46-
47-
Methods:
48-
49-
- <code title="post /search">client.search.<a href="./src/resources/search.ts">create</a>({ ...params }) -> SearchCreateResponse</code>

bin/check-release-environment

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ if [ -z "${NPM_TOKEN}" ]; then
66
errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets")
77
fi
88

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

1115
if [[ lenErrors -gt 0 ]]; then

bin/docker-tags

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# This script determines which Docker tags to use based on the version
6+
# It outputs a newline-separated list of tags
7+
8+
# Get version from mcp-server package.json
9+
if [ -f "packages/mcp-server/package.json" ]; then
10+
VERSION="$(jq -r -e '.version' ./packages/mcp-server/package.json)"
11+
else
12+
echo "ERROR: Could not determine version from packages/mcp-server/package.json" >&2
13+
exit 1
14+
fi
15+
16+
# Check if current version is pre-release (e.g. alpha / beta / rc)
17+
CURRENT_IS_PRERELEASE=false
18+
PRERELEASE_TAG=""
19+
if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then
20+
CURRENT_IS_PRERELEASE=true
21+
PRERELEASE_TAG="${BASH_REMATCH[1]}"
22+
fi
23+
24+
# Check if there's any stable release in Docker Hub
25+
# This matches the npm logic: check if ANY stable version exists
26+
DOCKER_IMAGE="${DOCKER_IMAGE:-perplexityai/perplexity-mcp}"
27+
HAS_STABLE_RELEASE=false
28+
29+
PAGE=1
30+
PAGE_SIZE=100
31+
32+
while true; do
33+
RESPONSE=$(curl -s --max-time 30 "https://hub.docker.com/v2/repositories/${DOCKER_IMAGE}/tags?page=${PAGE}&page_size=${PAGE_SIZE}")
34+
35+
if [ $? -ne 0 ]; then
36+
echo "ERROR: Failed to fetch tags from Docker Hub" >&2
37+
exit 1
38+
fi
39+
40+
# Check for 404 error - repository doesn't exist yet
41+
if echo "$RESPONSE" | jq -e '.message == "httperror 404: object not found"' >/dev/null 2>&1; then
42+
# Repository doesn't exist, no stable releases
43+
HAS_STABLE_RELEASE=false
44+
break
45+
fi
46+
47+
if ! echo "$RESPONSE" | jq -e '.results' >/dev/null 2>&1; then
48+
echo "ERROR: Invalid JSON response from Docker Hub" >&2
49+
echo "Response: $RESPONSE" >&2
50+
exit 1
51+
fi
52+
53+
# Check if any tags are stable versions (no pre-release suffix)
54+
STABLE_TAGS=$(echo "$RESPONSE" | jq -r '.results[].name | select(test("^[0-9]+\\.[0-9]+\\.[0-9]+$"))' 2>/dev/null || true)
55+
if [ -n "$STABLE_TAGS" ]; then
56+
HAS_STABLE_RELEASE=true
57+
break
58+
fi
59+
60+
NEXT_URL=$(echo "$RESPONSE" | jq -r '.next // empty')
61+
if [ -z "$NEXT_URL" ]; then
62+
break
63+
fi
64+
65+
PAGE=$((PAGE + 1))
66+
done
67+
68+
# Output tags based on the logic (matching npm):
69+
# 1. Always output the exact version tag
70+
echo "$VERSION"
71+
72+
# 2. Use pre-release tag (alpha/beta) if there's already a stable release and we're publishing a pre-release
73+
# Otherwise use 'latest'
74+
if $CURRENT_IS_PRERELEASE && $HAS_STABLE_RELEASE; then
75+
# Only tag with pre-release type, not latest
76+
echo "$PRERELEASE_TAG"
77+
else
78+
# Tag as latest (either it's a stable release, or it's a pre-release but no stable exists yet)
79+
echo "latest"
80+
81+
# For stable releases, also add major and major.minor tags
82+
if ! $CURRENT_IS_PRERELEASE && [[ "$VERSION" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
83+
MAJOR="${BASH_REMATCH[1]}"
84+
MINOR="${BASH_REMATCH[2]}"
85+
echo "$MAJOR"
86+
echo "$MAJOR.$MINOR"
87+
fi
88+
fi

packages/mcp-server/.dockerignore

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Dependencies
2+
node_modules/
3+
**/node_modules/
4+
5+
# Build outputs
6+
dist/
7+
**/dist/
8+
build/
9+
**/build/
10+
11+
# Git
12+
.git/
13+
.gitignore
14+
15+
# CI/CD
16+
.github/
17+
.gitlab-ci.yml
18+
.travis.yml
19+
20+
# IDE
21+
.vscode/
22+
.idea/
23+
*.swp
24+
*.swo
25+
*~
26+
27+
# OS
28+
.DS_Store
29+
Thumbs.db
30+
31+
# Documentation
32+
*.md
33+
docs/
34+
LICENSE
35+
36+
# Testing
37+
test/
38+
tests/
39+
__tests__/
40+
*.test.js
41+
*.spec.js
42+
coverage/
43+
.nyc_output/
44+
45+
# Logs
46+
*.log
47+
npm-debug.log*
48+
yarn-debug.log*
49+
yarn-error.log*
50+
51+
# Environment
52+
.env
53+
.env.*
54+
55+
# Temporary files
56+
*.tmp
57+
*.temp
58+
.cache/
59+
60+
# Examples and scripts
61+
examples/
62+
bin/
63+
64+
# Other packages (we only need mcp-server)
65+
packages/*/
66+
!packages/mcp-server/

packages/mcp-server/Dockerfile

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Build stage
2+
FROM node:20-alpine AS builder
3+
4+
# Install bash for build script
5+
RUN apk add --no-cache bash openssl
6+
7+
# Set working directory
8+
WORKDIR /build
9+
10+
# Copy entire repository
11+
COPY . .
12+
13+
# Install all dependencies and build everything
14+
RUN yarn install --frozen-lockfile && \
15+
yarn build
16+
17+
# Production stage
18+
FROM node:20-alpine
19+
20+
# Add non-root user
21+
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
22+
23+
# Set working directory
24+
WORKDIR /app
25+
26+
# Copy the built mcp-server dist directory
27+
COPY --from=builder /build/packages/mcp-server/dist ./
28+
29+
# Copy node_modules from mcp-server (includes all production deps)
30+
COPY --from=builder /build/packages/mcp-server/node_modules ./node_modules
31+
32+
# Copy the built @perplexity-ai/perplexity_ai into node_modules
33+
COPY --from=builder /build/dist ./node_modules/@perplexity-ai/perplexity_ai
34+
35+
# Change ownership to nodejs user
36+
RUN chown -R nodejs:nodejs /app
37+
38+
# Switch to non-root user
39+
USER nodejs
40+
41+
# The MCP server uses stdio transport by default
42+
# No exposed ports needed for stdio communication
43+
44+
# Set the entrypoint to the MCP server
45+
ENTRYPOINT ["node", "index.js"]
46+
47+
# Allow passing arguments to the MCP server
48+
CMD []

0 commit comments

Comments
 (0)