Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
f216186
Initial chat working in browser.
Jun 20, 2025
b5d8e1d
server add
juliux9 Jun 20, 2025
4340a41
new server
juliux9 Jun 20, 2025
92abe1b
Proxy implementation for playground.
Jun 20, 2025
ba6846f
Current state saved
Jun 20, 2025
034783d
Refactor mcp proxy locaiton + refactor tests to use websocket tunnel.
Jun 23, 2025
75e29ad
Fix all packages and dev to be able to start effectively for playground
Jun 23, 2025
0ed2521
Fix hibneraiton issues and status checks
Jun 23, 2025
eb73072
Realtime connection states donezo
Jun 24, 2025
250db73
Fix configuration for new mcps.
Jun 24, 2025
c47c05b
Package for external react components + example implementation
Jun 24, 2025
edc5865
docs(changeset): New MCP proxy support and Playground for local mcp t…
Jun 24, 2025
4b0b74c
Minor package bumps
Jun 24, 2025
46f4c70
temporary mcp tools server until we upgrade into index.ts
juliux9 Jun 24, 2025
836bbaf
Migrate to pnpm + update auto build and deps
Jun 24, 2025
b00d724
Migrate projects to pnpm
Jun 24, 2025
6a5401b
index.ts with tools
juliux9 Jun 24, 2025
996aa12
Working tool calls.
Jun 24, 2025
9eb1df5
Remove excessive logging
Jun 25, 2025
9917417
Fix reconnection logic for MCP client
Jun 25, 2025
8af61b5
Configure system prompts and advance usage from the ui
Jun 25, 2025
150b1b8
Error handling and user friendly responses.
Jun 25, 2025
111e746
Fix deps and cleanup old code thats not used
Jun 25, 2025
96b3d8b
Update to 1.13 consistent sdk across all .
Jun 25, 2025
ad53b25
docker updates with new dependencies
juliux9 Jun 25, 2025
50a0e1d
updated test figma
juliux9 Jun 25, 2025
61d142d
remove double
juliux9 Jun 25, 2025
ea3b9e6
small readme updates
juliux9 Jun 25, 2025
4d9e929
another README update
juliux9 Jun 25, 2025
f41b56b
Stash commit of work for playground
Jul 8, 2025
8f57eb2
Reconnect playground logic to UI.
Jul 8, 2025
573d586
Update pnpm-lock.yaml with new @radix-ui/react-tabs dependency and im…
Jul 10, 2025
a61c1f3
Animation for mcp server load
Jul 10, 2025
ebe955b
Production ready docker file
Jul 10, 2025
3016632
Fix builds
Jul 10, 2025
d2e38a7
Fix mcp toolbox builds
Jul 10, 2025
b720f53
Remove old builds
Jul 10, 2025
59def72
Fix misc build errors.
Jul 10, 2025
4f08410
Lint fixes
Jul 10, 2025
02bacb7
Ignore data!
Jul 10, 2025
ceaced9
And ignore db
Jul 10, 2025
6c2f7c9
Reorganize files and builds now bundled correctly.
Jul 10, 2025
28a3846
Fix mcp proxy to work with live registry image.
Jul 10, 2025
ce9aadb
Fix linting and various bugs
Jul 10, 2025
4d43cff
Fix linting errors
Jul 11, 2025
0865bd9
More linting fixes.
Jul 11, 2025
2d9c592
Refactor MCP server components to support installer preferences and C…
Jul 11, 2025
0f7167b
More lint fixes.
Jul 11, 2025
893d0d0
MOre lint fixes
Jul 11, 2025
94270cb
Update license to prevent platform competition
Jul 11, 2025
e9bc1b6
Fix lint
Jul 11, 2025
13051be
Fix crud-mcp build
Jul 11, 2025
2f1875e
Fix config.
Jul 11, 2025
177d62e
Fix images to be in the palyground showcase.
Jul 11, 2025
c45c747
ATtempt fix build linting
Jul 12, 2025
06767f0
Fix formatting for the landing page.
Jul 15, 2025
8599a04
Playground refactor.
Jul 17, 2025
162866b
docs(changeset): Introducing playround and mcp proxy support
Aug 11, 2025
1873e50
docs(changeset): playground introduction
Aug 11, 2025
337e706
Proper merge bump fixes.
Aug 11, 2025
6b76169
Fix compile errors
Aug 11, 2025
10878e5
Fix references
Aug 11, 2025
12d3a98
Fix linting errors
Aug 11, 2025
a00ec20
Linting consistency
Aug 11, 2025
58add53
Fix playground example linting errors
Aug 11, 2025
5463a27
Fix accidental ignore
Aug 11, 2025
464d2fa
Fix tests
Aug 11, 2025
437d80d
Fix build deps
Aug 11, 2025
2e310d7
Temp pause of crud MCP.
Aug 11, 2025
4d4dc4b
Delete incorrect vibe coded file
Aug 11, 2025
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
6 changes: 6 additions & 0 deletions .changeset/soft-vans-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@xava-labs/playground": patch
"@xava-labs/mcp": patch
---

playground introduction
127 changes: 127 additions & 0 deletions .github/workflows/cleanup-mcp-toolbox-preview-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Cleanup old preview Docker images for mcp-toolbox
name: Cleanup MCP Toolbox Preview Images

on:
schedule:
# Run daily at 2:00 AM UTC
- cron: '0 2 * * *'
workflow_dispatch:
# Allow manual trigger

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/mcp-toolbox

jobs:
cleanup-preview-images:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

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

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Clean up old preview images
uses: actions/github-script@v7
with:
script: |
const owner = context.repo.owner;
const packageName = '${{ env.IMAGE_NAME }}'.split('/').pop();

// Calculate cutoff date (7 days ago)
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.setDate() - 7);

let deletedCount = 0;
let totalChecked = 0;

try {
// Get all versions of the package
const { data: versions } = await github.rest.packages.getAllPackageVersionsForPackageOwnedByOrg({
package_type: 'container',
package_name: packageName,
org: owner,
per_page: 100
});

console.log(`Found ${versions.length} total package versions`);

for (const version of versions) {
totalChecked++;

// Check if this is a preview image (has pr- prefix in tags)
const isPreviewImage = version.metadata?.container?.tags?.some(tag =>
tag.startsWith('pr-') || tag.includes('-pr-')
);

if (!isPreviewImage) {
console.log(`Skipping non-preview version: ${version.id} (tags: ${version.metadata?.container?.tags?.join(', ') || 'none'})`);
continue;
}

const versionDate = new Date(version.created_at);

if (versionDate < cutoffDate) {
try {
await github.rest.packages.deletePackageVersionForOrg({
package_type: 'container',
package_name: packageName,
org: owner,
package_version_id: version.id
});

deletedCount++;
console.log(`✅ Deleted preview image version ${version.id} (created: ${version.created_at}, tags: ${version.metadata?.container?.tags?.join(', ') || 'none'})`);
} catch (error) {
console.log(`❌ Failed to delete version ${version.id}: ${error.message}`);
}
} else {
console.log(`⏭️ Keeping recent preview version ${version.id} (created: ${version.created_at})`);
}
}

// Generate summary
const summary = `## 🧹 MCP Toolbox Preview Image Cleanup

**Cleanup Summary:**
- **Total versions checked:** ${totalChecked}
- **Preview images deleted:** ${deletedCount}
- **Cutoff date:** ${cutoffDate.toISOString()}

**Retention Policy:**
- Preview images older than 7 days are automatically deleted
- Production images (\`latest\`, \`main-*\`, version tags) are preserved

${deletedCount > 0 ? '✅ Cleanup completed successfully' : 'ℹ️ No preview images needed cleanup'}
`;

console.log(summary);

// Write to job summary
require('fs').appendFileSync(process.env.GITHUB_STEP_SUMMARY, summary);

} catch (error) {
console.error('Error during cleanup:', error);

const errorSummary = `## ❌ MCP Toolbox Preview Image Cleanup Failed

**Error:** ${error.message}

**Details:**
- Package: \`${packageName}\`
- Registry: \`${{ env.REGISTRY }}\`
- Organization: \`${owner}\`
`;

require('fs').appendFileSync(process.env.GITHUB_STEP_SUMMARY, errorSummary);
throw error;
}
118 changes: 118 additions & 0 deletions .github/workflows/mcp-toolbox-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Build and push preview Docker images for the mcp-toolbox package
name: MCP Toolbox Preview Build

on:
pull_request:
branches: [main, develop]
paths:
- 'packages/mcp-toolbox/**'
- 'packages/mcp/**'
- 'packages/mcp-proxy/**'
- '.github/workflows/mcp-toolbox-preview.yml'

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/mcp-toolbox

jobs:
build-preview:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
pull-requests: write

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

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=pr
type=sha,prefix=pr-${{ github.event.number }}-

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

- name: Comment PR with image info
uses: actions/github-script@v7
with:
script: |
const { data: comments } = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});

const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('🐳 Preview MCP Toolbox Docker Image')
);

const commentBody = `🐳 **Preview MCP Toolbox Docker Image Built**

**Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.number }}\`

**Tags:**
${{ steps.meta.outputs.tags }}

**Usage:**
\`\`\`bash
# Pull the preview image
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.number }}

# Run the MCP Toolbox server
docker run -p 11990:11990 \\
-e PROXY_ID=preview-toolbox-${{ github.event.number }} \\
-e MCP_SERVER_HOST=host.docker.internal:6050 \\
--add-host host.docker.internal:host-gateway \\
-v \$(pwd)/data:/app/data \\
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.number }}
\`\`\`

**Health Check:**
\`\`\`bash
curl http://localhost:11990/health
\`\`\`

**Note:** Preview images are automatically cleaned up after 7 days.
`;

if (botComment) {
await github.rest.issues.updateComment({
comment_id: botComment.id,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
});
} else {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
});
}
133 changes: 133 additions & 0 deletions .github/workflows/mcp-toolbox-production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Build and push production Docker images for the mcp-toolbox package
name: MCP Toolbox Production Build

on:
push:
branches: [main]
paths:
- 'packages/mcp-toolbox/**'
- 'packages/mcp/**'
- 'packages/mcp-proxy/**'
- '.github/workflows/mcp-toolbox-production.yml'
release:
types: [published]

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/mcp-toolbox

jobs:
build-production:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

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

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}

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

- name: Generate deployment summary
run: |
echo "## 🚀 MCP Toolbox Docker Image Deployed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Registry:** \`${{ env.REGISTRY }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Tags:**" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Usage:**" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "# Pull the latest image" >> $GITHUB_STEP_SUMMARY
echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "# Run the MCP Toolbox server" >> $GITHUB_STEP_SUMMARY
echo "docker run -p 11990:11990 \\" >> $GITHUB_STEP_SUMMARY
echo " -e PROXY_ID=your-unique-proxy-id \\" >> $GITHUB_STEP_SUMMARY
echo " -e MCP_SERVER_HOST=host.docker.internal:6050 \\" >> $GITHUB_STEP_SUMMARY
echo " -e PORT=11990 \\" >> $GITHUB_STEP_SUMMARY
echo " -e DB_PATH=/app/data/packages.db \\" >> $GITHUB_STEP_SUMMARY
echo " --add-host host.docker.internal:host-gateway \\" >> $GITHUB_STEP_SUMMARY
echo " -v \$(pwd)/data:/app/data \\" >> $GITHUB_STEP_SUMMARY
echo " ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

- name: Update package description
uses: actions/github-script@v7
with:
script: |
const packageName = `${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}`.toLowerCase();

try {
await github.rest.packages.updatePackageForOrg({
package_type: 'container',
package_name: packageName.split('/').pop(),
org: context.repo.owner,
description: 'MCP Toolbox - A lightweight, bundled WebSocket server for managing MCP (Model Context Protocol) packages with pure JavaScript SQLite persistence',
homepage_url: `https://github.com/${context.repo.owner}/${context.repo.repo}`,
public: true
});
console.log('✅ Package description updated successfully');
} catch (error) {
console.log('⚠️ Could not update package description:', error.message);
}

security-scan:
runs-on: ubuntu-latest
needs: build-production
permissions:
contents: read
packages: read
security-events: write

steps:
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
format: 'sarif'
output: 'trivy-results.sarif'

- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
Loading