Using private npm packages in hosted servers
Organizations often maintain internal npm packages for shared utilities, proprietary integrations, or security-sensitive code. Hosted connectors run self-contained container images and install nothing at startup, so install private packages when you build the image. Pass the registry token as a Docker build secret, which keeps it out of the image layers and out of Mintive entirely.
1. Identify required credentials
Determine what authentication your private registry requires:
- npm Enterprise or GitHub Packages: Authentication token
- JFrog Artifactory: Token or username/password
- Azure Artifacts: Personal access token
- Custom registry: Check registry documentation
2. Write an .npmrc for the build
Create an .npmrc outside your build context (for example in your home directory) that maps your package scope to the registry and holds the token:
@myorg:registry=https://registry.mycompany.com/
//registry.mycompany.com/:_authToken=<auth-token>
Add one registry line per scope and one _authToken line per registry host if you pull from several registries. See Common registry configurations for exact values.
3. Install the package in the Dockerfile
Mount the .npmrc as a build secret only for the install step:
# syntax=docker/dockerfile:1
FROM node:22-slim
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm install -g @myorg/private-mcp-server
Then build for the hosted platform, passing the secret:
docker build --platform linux/amd64 \
--secret id=npmrc,src=$HOME/.npmrc \
-t private-mcp-server:1.0.0 .
The secret exists only while that RUN step executes, so the token isn't written into any image layer.
4. Push the image to Mintive and deploy it
Hosted connectors can only pull public images, and this image contains your private packages, so don't publish it to Docker Hub or a public GHCR repository. Push it to Mintive's managed registry with the Admin MCP instead. Images there are scoped to your organization.
-
In an AI client connected to the Admin MCP, call
create_registry_push_session. It returns animageRef, aregistryHost, ausername, a short-livedcredentialUrl, and afinalizeToken. -
Tag the image you built in step 3, log in, and push it:
docker tag private-mcp-server:1.0.0 <imageRef>
curl -fsSL '<credentialUrl>' | docker login <registryHost> -u <username> --password-stdin
docker push <imageRef>Piping the credential URL into
docker loginkeeps the registry password out of your shell history and the chat. -
Call
deploy_pushed_imagewith thefinalizeTokenand aconfigfor the new connector. For a stdio server, set the transport to stdio and the command to the package's executable name (for exampleprivate-mcp-server). For an HTTP server whose image sets its own entrypoint, leave the command unset.
You can also ask the assistant to run these steps for you. Tell it the image is already built locally, so it pushes private-mcp-server:1.0.0 instead of rebuilding without the build secret.
npx @mintmcp/hosted-cli build-and-push also pushes to the managed registry, but it can't pass a build secret, so use the Admin MCP for this image.
See Deploy Docker-based hosted connectors for the full image requirements.
Security considerations
- Token permissions: Use tokens with minimal required permissions (read-only package access)
- Token rotation: Establish a rotation schedule for shared tokens
- No token in the image: Build secrets aren't stored in image layers, so anyone who can pull the image can't recover the registry token
- Least privilege: Prefer scoped package authentication over global registry credentials
Common registry configurations
GitHub Packages
@myorg:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=<github-pat>
Required GitHub token scopes: read:packages
Azure Artifacts
@myorg:registry=https://pkgs.dev.azure.com/myorg/_packaging/myfeed/npm/registry/
//pkgs.dev.azure.com/myorg/_packaging/myfeed/npm/registry/:_authToken=<azure-pat>
Required Azure DevOps token scopes: Packaging (read)
JFrog Artifactory
@myorg:registry=https://mycompany.jfrog.io/artifactory/api/npm/npm-local/
//mycompany.jfrog.io/artifactory/api/npm/npm-local/:_authToken=<artifactory-token>
Troubleshooting
Build fails with 401, 404, or invalid token/password errors
- Verify the registry URL is correct
- Confirm the package name and scope match your registry configuration
- Check that the token has read access to the package
- Check that you passed
--secret id=npmrc,...and that theidmatches the--mountin the Dockerfile
Authentication fails
- Verify the token is not expired
- Check that the registry path in the
_authTokenline matches the registry URL exactly (including trailing slashes) - For scoped packages, ensure the
@scope:registryline names the right scope
Existing connectors
Hosted connectors created earlier from a pasted STDIO JSON config, which install packages at startup using npm_config_ environment variables, keep running unchanged.
Next steps
- Admin MCP - Push and deploy images from your AI client
- MCP connectors overview - Understand connector types