Build an MCP server, scaffold a manifest, and publish it to the Syphon registry — signed and ready to install.
Use syphon create to scaffold a new package from scratch, or syphon init to add a manifest to an existing project directory. Both prompt for required fields and write syphon.json.
# new project from scratch (creates directory + scaffolds)$ syphon create my-mcp-server$# or add a manifest to an existing project$ cd my-existing-project$ syphon init# Package name [my-mcp-server]: my-mcp-server# Version [0.1.0]:# Description: Wraps the Stripe API for AI agents# Runtime (node/bun/python/deno/binary) [node]:# Entry [dist/index.js]:# License [MIT]:# ✓ Created syphon.json
Pass -y to accept all defaults without prompts.
After scaffolding, edit syphon.json to declare your tools and environment variables. This is what users see on the registry page.
{
"name": "my-mcp-server",
"version": "0.1.0",
"description": "Wraps the Stripe API for AI agents",
"license": "MIT",
"author": "Misbah",
"runtime": "node",
"entry": "dist/index.js",
"mcp_version": "1.0.0",
"category": "finance",
"keywords": ["stripe", "payments", "billing"],
"frameworks": ["claude-code", "cursor", "generic"],
"tools": [
{ "name": "create_payment", "description": "Creates a Stripe payment intent" },
{ "name": "list_invoices", "description": "Lists recent invoices for a customer" }
],
"env": [
{
"name": "STRIPE_SECRET_KEY",
"required": true,
"description": "Stripe secret key — get it from dashboard.stripe.com/apikeys"
}
]
}See the Manifest Reference for all fields, constraints, and validation rules.
Before publishing, verify what files will be included:
$ syphon pack --dry-run# → Files (8):# dist/index.js 24.3 KB# syphon.json 0.8 KB# README.md 2.1 KB# ...# → Total: 27.2 KB# → Excluded (312):# node_modules/...# src/...
Create a .syphonignore file (same syntax as .gitignore) to exclude files. By default node_modules/, .git/, and common build artefacts are excluded.
To write the tarball to disk without publishing:
$ syphon pack
Both syphon pack and syphon publish scan every included file for credentials before touching the network. If a hard-block pattern is found, the command exits immediately:
$ syphon publish# ✗ Refusing to publish: secrets detected.# .env:3 AWS_SECRET_KEY AKIAIOSFODNN7EXAMPLE$# fix: add .env to .syphonignore, then retry
Hard-block patterns include AWS access keys, GitHub PATs, Stripe secret keys, private key PEM blocks, and connection strings with embedded passwords. Soft-block patterns (like generic high-entropy strings) print a warning but don't stop the publish.
Never commit secrets
.env, *.pem, and *credentials* to your .syphonignore. Secret scanning is a last resort, not a substitute for not committing secrets.Every package is signed with an ed25519 key unique to your account. The signing key is generated at login and stored at ~/.syphon/keys/signing.key. The public half is registered with the registry so installers can verify provenance.
# login creates a local signing key and registers its public half$ syphon login
$ syphon publish# ✓ 1/Pack 8 files, 27.2 KB# ✓ 2/Sign Signed# ✓ 3/Upload ↑ Uploading my-mcp-server@0.1.0…# ✓ 4/Confirm# ✓ Published my-mcp-server@0.1.0# 27.2 KB · sha256 a3f8b2c1… · signed by Misbah
Publish runs validation, secret scanning, packing, signing, and upload — in that order. It stops at the first failure so you never upload a broken package.
After packing, Syphon checks for common mistakes:
dist/index.js contains require() calls to non-Node-builtins, Syphon warns that users will get MODULE_NOT_FOUND errors. Bundle first:$ esbuild src/index.ts --bundle --platform=node --outfile=dist/index.js
requirements.txt or pyproject.toml, users won't know what to pip install. Add one before publishing."entry" doesn't exist, Syphon warns to compile the binary before publishing.# publish as a pre-release under the "beta" tag$ syphon publish --tag beta$# combined with a release candidate tag$ syphon publish --tag rc
The default tag is latest. All packages are currently published as public. Private packages are planned for a future release.
You have a 72-hour window to unpublish a version. After that, only a yank is possible (the version still exists in the registry but is excluded from normal resolution).
$ syphon unpublish my-mcp-server@0.1.0# Unpublish my-mcp-server@0.1.0? This cannot be undone within the 72h window. [y/N] y# ✓ Unpublished my-mcp-server@0.1.0