Skip to main content

Publish & verify an MCP server

Applies to SDK 0.16+ · Last updated: 2026-06-12

This guide is for developers who want to list their own MCP server in the AgentNode registry. If instead you want to use AgentNode as an MCP server inside Claude Code or Cursor, see MCP Integration — that is the consumer side and unrelated to publishing.

AgentNode lists MCP servers that are already published on npm or PyPI. No code is uploaded — you point AgentNode at the package with a manifest, and AgentNode re-verifies the package, its version, ownership, and (via an automated sandbox smoke check) that the server starts and answers the MCP protocol. A passing check is a review signal only: MCP listings stay review-gated and a human approves them — nothing is auto-published.

The flow at a glance

lifecycle
init --type mcp   →  scaffold a manifest
edit + pin        →  set npm/PyPI package, pin the exact version, declare permissions
mcp verify        →  local checks (schema, package/version, permissions)
mcp submit        →  server re-verifies authoritatively; enters review
mcp ownership     →  prove you control the package (publish-challenge)
sandbox smoke     →  AgentNode starts the server in an isolated sandbox
mcp status        →  track review + gate signals
review            →  a human approves; only then can it be published

Prerequisites

  • The AgentNode CLI installed (see Installation) and an API key available as AGENTNODE_API_KEY (or passed with --token).
  • A publisher profile on your account (submitting requires one).
  • Your MCP server already published as a public npm or PyPI package, at a concrete version (not a floating tag).
  • A launch command that starts the server over stdio — e.g. npx -y your-pkg@1.2.3 (npm) or uvx your-pkg==1.2.3 (PyPI).
  • The source repository that owns the package (used for ownership checks).

1 — Scaffold the listing

Create a listing project with an MCP manifest and a README:

terminal
$ agentnode init --type mcp

This writes an agentnode.yaml (manifest version 0.3, runtime: mcp) with placeholders you must fill in, plus a README.md with the verify → submit steps. Unlike a tool pack, an MCP listing uploads no code — it only references the upstream npm/ PyPI package.

2 — The manifest

The listing is described by agentnode.yaml. The MCP-specific fields live under mcp_server. Fill in exactly one of npm_package / pypi_package, pin the version in command, and set source_repo to the repo that owns the package.

Required fields

FieldExampleNotes
manifest_version"0.3"Fixed
runtime"mcp"Identifies the listing as an MCP server
package_id"example-mcp"Catalog slug
name / summary / description"Example MCP"Display metadata
version"1.0.0"The listing version (semver)
publisher"your-publisher-slug"Your publisher identifier
mcp_server.command["npx","-y","example-mcp@1.2.3"]Launch command — must PIN the exact version
mcp_server.npm_package OR pypi_package"example-mcp"Exactly one; the other omitted
mcp_server.source_repo"https://github.com/you/example-mcp"Must match the package's registry metadata

Example — npm-backed MCP

agentnode.yamlyaml
manifest_version: "0.3"
package_id: "example-mcp"
package_type: "toolpack"
name: "Example MCP"
publisher: "your-publisher-slug"
version: "1.0.0"
summary: "An example MCP server listing."
description: |
  Lists an existing npm MCP server in the AgentNode catalog.

runtime: "mcp"
install_mode: "package"
hosting_type: "agentnode_hosted"

mcp_server:
  command: ["npx", "-y", "example-mcp@1.2.3"]   # pin the EXACT version
  npm_package: "example-mcp"
  source_repo: "https://github.com/your-org/example-mcp"

tags: []
categories: []
compatibility:
  frameworks: ["generic"]

# Declare honestly — verification compares this against what the server requests.
permissions:
  network:
    level: "restricted"
    allowed_domains: []
  filesystem:
    level: "none"
  code_execution:
    level: "none"
  data_access:
    level: "input_only"
  user_approval:
    required: "high_risk_only"

Example — PyPI-backed MCP

Same manifest, but swap the mcp_server block to use pypi_package and a uvx command with a == version pin:

agentnode.yaml (mcp_server block)yaml
mcp_server:
  command: ["uvx", "example-mcp==1.2.3"]        # pin with ==
  pypi_package: "example-mcp"
  source_repo: "https://github.com/your-org/example-mcp"

The names above are placeholders — replace them with your real package and repo.

3 — Pin the package version

The version must be pinned in mcp_server.command@1.2.3 for npm, ==1.2.3 for PyPI. An unpinned command (e.g. npx -y example-mcp with no version) is not reproducible and is flagged on verify and submit. A verification result is bound to that exact package + version + command, so publishing a new package version means re-verifying and re-submitting the listing for the new version.

4 — Verify locally

Run the local checks against your manifest. Add --test to also start the server and run the MCP initialize + tools/list handshake locally; add --json to get the machine-readable report (this is what mcp submit attaches).

terminal
$ agentnode mcp verify .              # schema, package, version, permission checks
$ agentnode mcp verify . --test       # also run the local protocol test
$ agentnode mcp verify . --json       # JSON report (attach on submit)

The report ends in a status such as TESTED (protocol test passed), RESOLVED (package + version resolved), REVIEW_NEEDED, MAINTAINER_ACTION_REQUIRED, or INVALID. The command exits non-zero on INVALID, so it is CI-gateable. Local verification is a helpful pre-check — it does not replace the server-side re-verification, ownership proof, or the sandbox smoke check below.

5 — Submit for the catalog

Submit the manifest and its verification report. Use --dry-run to verify without sending; --test to run the protocol test first. Authentication uses --token or AGENTNODE_API_KEY.

terminal
$ agentnode mcp submit . --token $AGENTNODE_API_KEY
$ agentnode mcp submit . --dry-run    # verify only, don't send

On submit, AgentNode re-verifies the registry facts itself (package existence, resolved version, repo consistency) — your local report is advisory; the server result is authoritative. You get a submission id and a starting status. A submission never goes live automatically.

You can have only one open submission for the same package + version at a time — a second one is rejected as a duplicate until the first is resolved.

6 — Prove package ownership

Ownership is a separate axis from the source-repo match: you prove you can publish the package with a one-time publish-challenge. Issue a challenge, add the returned keyword to your package and publish a new version (only someone with publish rights can), then verify.

terminal
# 1. issue a one-time challenge (token is shown once)
$ agentnode mcp ownership challenge example-mcp --registry npm --token $AGENTNODE_API_KEY

# 2. add the returned keyword to your package metadata, publish a new version

# 3. verify — checks the latest published version for the keyword
$ agentnode mcp ownership verify example-mcp --registry npm --token $AGENTNODE_API_KEY

verify reports one of:

StatusMeaningNext step
verifiedThe keyword was found in the latest published version — ownership recordedNothing — you're done (the claim is time-limited; re-verify if it later expires)
pendingChallenge issued, keyword not yet found in a published versionPublish a new version with the keyword, then verify again
expiredThe challenge's time window elapsedIssue a new challenge and retry
package-not-foundThe package doesn't resolve on the registryCheck the registry + package name
registry-unavailableThe registry was temporarily unreachableRetry verify shortly (transient)

Verifying ownership publishes nothing on its own — it is one of the signals a reviewer needs before a listing can go live.

7 — The automated sandbox smoke check

After you submit, AgentNode runs an automated sandbox smoke check for npm/PyPI MCP submissions. It is a technical executability + protocol check, not a safety or trust guarantee.

What it checks

  • the pinned package can be installed in an isolated sandbox,
  • the MCP server starts,
  • it answers the MCP initialize flow, and
  • it answers tools discovery (tools/list).

What it does not do

  • It is not a full security audit, and it is not a safety or trustworthiness certification of the package.
  • It does not assess functional quality, and does not guarantee every later use will succeed.

How it runs

The check runs with restricted permissions and bounded resources, with the install phase separate from the run phase; the run phase is network-isolated, and the sandbox is cleaned up automatically afterward.

Result semantics

ResultMeaningEffect
passedThe server started and answered initialize + tools discoveryA positive review signal (does not auto-publish)
failed (startup crash / protocol error / tools/list error)The server is objectively brokenBlocks — fix and resubmit
failed (install / timeout / registry issue)A transient/environmental problemKept for review; can be rechecked — not an auto-reject
deferred (host resources low)The host was momentarily low on RAM/disk, so the check was not runKept for review; can be rechecked later
unavailable / skippedThe check could not run (e.g. credentials required)Kept for review

A temporary infrastructure problem never auto-rejects a submission, and a passing check never auto-publishes it — it is one input to the human review.

8 — Track your submission

terminal
$ agentnode mcp status <submission_id> --token $AGENTNODE_API_KEY
$ agentnode mcp status <submission_id> --json

The status reflects where the submission is in review:

StatusShown asMeaning
pending / quarantined_reviewUnder ReviewHeld for human review — not live
action_requiredAction RequiredA check needs fixing — update and resubmit
needs_changesChanges RequestedA reviewer asked for changes
approvedApprovedCleared for publication — still not live yet
rejectedNot AcceptedNot accepted
published(live)Live in the catalog

9 — Review & listing

  • MCP submissions remain review-gated. The technical gates (registry verification, ownership, sandbox smoke) are inputs to a human review — they are not the decision.
  • Publishers cannot publish their own listing. Publishing is an administrative action; a passing smoke plus verified ownership does not make a listing live on its own.
  • Approval (approved) means a reviewer cleared it — it is a pre-publish state, still not live, until it is actually published.
  • A listing may still require additional editorial or security review before it goes live.

10 — Changes & new versions

  • Publishing a new package version means a new listing version: re-run mcp verify and mcp submit for it (verification is bound to the exact package + version + command).
  • While a submission is action_required or needs_changes, you fix the manifest and re-submit an updated verification report for the same package.
  • A verified ownership claim is time-limited; if it expires, issue a new challenge and verify again.
  • Re-running the registry verification on an existing submission (for example if a registry was temporarily unavailable) is a reviewer action, not a publisher one.

Troubleshooting

You seeMeaningNext step
Manifest runtime must be 'mcp'runtime is not set to mcpSet runtime: "mcp"
Manifest must have mcp_server blockmcp_server is missingAdd the mcp_server block with command + npm/pypi_package
Package / version not foundThe package or pinned version isn't on the registryPublish it, or fix the name/version in command
Command is not pinnedThe launch command has no exact versionPin @x.y.z (npm) or ==x.y.z (PyPI)
Verification report status is not valid / INVALIDThe attached report is missing or INVALIDRe-run agentnode mcp verify . --test --json
An open submission already existsA duplicate for the same package + version is in the pipelineWait for it to resolve, or update that submission
No publish-challenge to verifyYou ran verify before issuing a challengeRun mcp ownership challenge first
The challenge has expiredThe challenge window elapsedIssue a new challenge and retry
Smoke: startup crash / protocol error / tools/list errorThe server is objectively broken in the sandboxFix the server, publish a fixed version, resubmit
Smoke: install / timeout / resourcesA transient or environmental issueIt stays reviewable and can be rechecked — no action needed to avoid rejection

Security & trust model

  • The sandbox smoke is a limited technical check (does it start and speak the protocol), not a comprehensive security certification.
  • You remain responsible for the package and code you list.
  • Do not put secrets in the manifest. If the server needs credentials, declare only the required environment keys — never paste tokens or credentials into manifests, reports, or logs.
  • A registry listing is not a guarantee of safety; users should still review third-party MCP servers before use.

Full quick sequence

terminal
# 1. scaffold
$ agentnode init --type mcp

# 2. edit agentnode.yaml: set npm_package/pypi_package, pin the version in
#    command, set source_repo, declare permissions

# 3. verify locally
$ agentnode mcp verify . --test --json

# 4. submit (server re-verifies authoritatively; enters review)
$ agentnode mcp submit . --token $AGENTNODE_API_KEY

# 5. prove ownership
$ agentnode mcp ownership challenge <package> --registry npm --token $AGENTNODE_API_KEY
#    ...add the keyword, publish a new version...
$ agentnode mcp ownership verify <package> --registry npm --token $AGENTNODE_API_KEY

# 6. track status (a human reviews; listings stay review-gated)
$ agentnode mcp status <submission_id> --token $AGENTNODE_API_KEY

For the individual commands see the CLI Reference. To use AgentNode itself as an MCP server in your editor, see MCP Integration.