A public, self-hostable MCP server for Nango management and provider API access.
Created by Lev Jampolsky at ValStratis.
This independent project is not affiliated with or endorsed by Nango. See Nango, the Nango repository, and Nango documentation.
Version 2.0 provides:
- stdio by default and optional Streamable HTTP at
/mcp - direct environment secrets or optional Infisical resolution
- static bearer policies or OAuth protected-resource authorization for HTTP
- 28 tools with strict camelCase inputs and documented connection filters
- native MCP approval flows, including conservative trusted-host review for exact-target provider deletes
- redacted Nango management responses
- safe native connection end-user updates with preflight and read-back verification
- provider requests through Nango Proxy with safe 429 retry behavior
- immutable staging for large outbound mutation bodies
- bounded structured results and contract-v2 response artifacts with a query-only JSON boundary
- streamed provider downloads exposed as protected MCP resources
Run directly with uvx:
uvx --from git+https://github.com/LevSky22/nango-mcp-server.git@v2.0.0 nango-mcpOr install persistently:
pipx install git+https://github.com/LevSky22/nango-mcp-server.git@v2.0.0For development:
git clone https://github.com/LevSky22/nango-mcp-server.git
cd nango-mcp-server
python3 -m venv .venv
.venv/bin/pip install -e ".[test]"
.venv/bin/python -m pytest -qCreate a private .env file:
NANGO_BASE_URL=https://api.nango.dev
NANGO_ENVIRONMENT=default
NANGO_SECRET_KEY=replace_with_your_nango_environment_secret_keyNANGO_SECRET_KEY is the Nango environment secret key, not a provider credential. Keep it server-side and never commit it.
For several environments:
NANGO_MCP_ENVIRONMENTS=development,production
NANGO_SECRET_KEY_DEVELOPMENT=replace_with_development_secret
NANGO_SECRET_KEY_PRODUCTION=replace_with_production_secret
NANGO_MCP_ENVIRONMENT_ALIASES_PRODUCTION=livePoint the process at the file when its working directory differs:
NANGO_MCP_ENV_FILE=/absolute/path/to/.env nango-mcpGeneric MCP client configuration:
{
"mcpServers": {
"nango": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/LevSky22/nango-mcp-server.git@v2.0.0",
"nango-mcp"
],
"env": {
"NANGO_MCP_ENV_FILE": "/absolute/path/to/.env"
}
}
}
}Stdio is the default. It uses a local implicit caller scope over the configured environments. Set NANGO_MCP_READ_ONLY=true to disable mutations entirely.
HTTP mode binds to loopback by default and requires authentication plus rotating request-state keys:
NANGO_MCP_TRANSPORT=http
NANGO_MCP_HTTP_HOST=127.0.0.1
NANGO_MCP_HTTP_PORT=3000
NANGO_MCP_REQUEST_STATE_KEYS=replace_with_at_least_32_random_bytesGET /health is an unauthenticated shallow health check. MCP traffic uses /mcp.
Static mode is suited to local and private-network deployments. Tokens must start with nangomcp1_ and contain at least 43 URL-safe random characters. Store only their lowercase SHA-256 digests:
python -c 'import hashlib; print(hashlib.sha256(input().strip().encode()).hexdigest())'NANGO_MCP_AUTH_MODE=static
NANGO_MCP_TOKENS={"replace_with_sha256_digest":{"label":"local-automation","scopes":["development"],"allowed_proxy_methods":["GET","HEAD"],"mutation_approval":"server"}}Policy fields are:
label: non-secret audit identityscopes: environment names or['*']denied_tools: optional tool namesallowed_proxy_methods: methods or['*']denied_proxy_path_patterns: optional regular expressionsmutation_approval:serverorhostserver_approval_proxy_path_patterns: routes that remain server-approved
Use NANGO_MCP_TOKEN_REGISTRY_FILE instead of inline JSON for atomic hot reloads.
OAuth mode expects an external authorization server and validates opaque access tokens through RFC 7662 introspection:
NANGO_MCP_AUTH_MODE=oauth
NANGO_MCP_OAUTH_ISSUER_URL=https://identity.example.com
NANGO_MCP_OAUTH_RESOURCE_URL=https://mcp.example.com/mcp
NANGO_MCP_OAUTH_INTROSPECTION_URL=https://identity.example.com/oauth/introspect
NANGO_MCP_OAUTH_CLIENT_ID=nango-mcp-resource-server
NANGO_MCP_OAUTH_CLIENT_SECRET=replace_with_resource_server_secret
NANGO_MCP_OAUTH_REQUIRED_SCOPES=nango-mcpAccess tokens use these scopes:
nango-mcp: required base scopenango:env:<name>ornango:env:*: environment accessnango:read: read intentnango:write: mutation accessnango:proxy+nango:read: proxy GET/HEAD/OPTIONS and downloadsnango:proxy+nango:write: proxy mutations and request-body staging
Issuer, resource, and introspection URLs must use HTTPS except for loopback development. The server validates activity, expiry, required scopes, and audience/resource.
Mutation tools use MCP-native approval flows. There are no confirmation-string arguments.
mutation_approval=serverasks for server-bound approval on every mutation.mutation_approval=hostdelegates routine writes to host policy.- exact-target provider DELETE routes may be delegated to a trusted host; alphabetic collection routes, bulk/wildcard/template paths, query/body deletes, and ambiguous targets remain server-approved.
- matching proxy routes can be forced back to server approval.
Approval state is time-limited and bound to the caller policy, environment, tool, arguments, effect, and current target snapshot. Modern MCP clients receive input_required; compatible older sessions use elicitation.
proxy_request never emits an unbounded model-facing result. Small JSON responses remain inline. Large responses are stored privately and returned as:
- a bounded preview in
structuredContent responseMetawith completeness, pagination, and artifact metadata- an optional descriptor
resource_linkusingnango-mcp://artifact/<id>
resources/read returns bounded metadata only and never the stored provider payload. Models use query_response_artifact as the sole JSON value reader for bounded selection, projection, filtering, shape description, pagination, keyed-object entries, or literal text search. Binary links returned by download_provider_file remain directly readable resources.
This hybrid follows MCP's separation of concerns: tools initiate computation, resources carry application-controlled context, and resource links let hosts decide whether full content enters model context. See the MCP guidance for resources and tools.
Defaults:
- inline target: 32 KiB
- stored-result preview: 8 KiB
- hard emitted result limit: 128 KiB
- artifact limit: 50 MiB
- artifact TTL: 24 hours
- artifact quota: 1 GiB
- artifact directory/file modes:
0700/0600
Override storage with NANGO_MCP_ARTIFACT_ROOT, NANGO_MCP_ARTIFACT_MAX_BYTES, and NANGO_MCP_ARTIFACT_TTL_SECONDS.
download_provider_file streams a provider GET with Accept: */*, enforces the size limit, computes SHA-256, and returns nango-mcp://download/<id> as a protected resource link. Results never expose a server filesystem path.
Every tool uses strict camelCase wire names. Unknown arguments and legacy snake_case spellings are rejected.
proxy_request accepts:
environment, providerConfigKey, connectionId, method, path,
query, headers, baseUrlOverride, body, bodyArtifactId, responseMode,
responsePath, fields, filters, pageSize, cursor
MCP-owned response fields include contentType, responseHeaders, rateLimit, and responseMeta. Provider JSON under response is preserved exactly.
For mutation requests, inline bodies are limited to 4 KiB, 40 total collection entries, and JSON depth 8. If a body exceeds any limit, call stage_proxy_request_body with the same environment and body, then retry proxy_request with the returned bodyArtifactId and omit body. Staged bodies are immutable, expiring, digest-verified immediately before transmission, and have no raw-read or query interface.
query_response_artifact accepts:
environment, artifactId, responsePath, fields, filters,
pageSize, cursor, describe, objectMode, textSearch
Paths use RFC 6901 JSON Pointer. Exact document pointers win; when an absolute pointer is absent, the server tries it once beneath the advertised /response root and reports the canonical path. pageSize defaults to 20 and is capped at 100. Contract-v2 cursors are signed and bound to the caller, environment, artifact, and query view.
Rate-limit handling distinguishes Nango gateway throttles from forwarded provider throttles by Nango's response body. Gateway rejections are safe to retry for any method because they were not forwarded. Provider rejections are replayed only for GET, HEAD, and OPTIONS.
The server exposes 28 tools, grouped by workflow:
| Area | Tools | Access |
|---|---|---|
| Environments | list_environments, check_environment |
Read |
| Provider discovery | search_provider_templates, download_provider_file |
Read |
| Integrations | list_integrations, get_integration, create_integration, update_integration, delete_integration |
Read/write |
| Connections | list_connections, get_connection, get_connection_context, refresh_connection_credentials, import_connection, delete_connection, update_connection_end_user |
Read/write |
| Tags and metadata | replace_connection_tags, update_connection_metadata |
Write |
| Connect sessions | create_connect_session, create_standard_connect_session, create_reconnect_session |
Write |
| Provider API and large responses | stage_proxy_request_body, proxy_request, query_response_artifact |
Read/write |
| Optional connection conventions | describe_connection_convention, build_connection_convention, apply_connection_convention, audit_connection_conventions |
Read/write |
See the complete tool reference for each tool's purpose, important inputs, result behavior, and safety notes. The MCP tools/list schema remains authoritative for exact input types and required fields.
Management responses redact credential-like fields. refresh_connection_credentials returns only a non-secret summary. Proxy methods other than GET/HEAD/OPTIONS and all other mutations follow the approval policy described above.
The connection convention helpers are optional. They generate generic Nango tags and metadata; they are not profiles and do not discover organizations or impose deployment-specific policy. update_connection_end_user is deliberately separate: it changes Nango's native end_user identity, preserves both tag layers, blocks organization-linked identities, and verifies the result by read-back.
NANGO_MCP_SECRET_RESOLVER=infisical
NANGO_MCP_ENVIRONMENTS=development,production
INFISICAL_URL=https://infisical.example.com
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=replace_with_machine_identity_id
INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=replace_with_machine_identity_secret
NANGO_MCP_INFISICAL_PROJECT_ID=replace_with_project_id
NANGO_MCP_INFISICAL_ENVIRONMENT=production
NANGO_MCP_INFISICAL_SECRET_PATH_TEMPLATE=/nango/{environment}
NANGO_MCP_INFISICAL_SECRET_NAME=NANGO_SECRET_KEYBuild locally:
docker build -t nango-mcp:2.0.0 .HTTP containers must receive the Nango secret configuration, authentication policy, and request-state keys at runtime. Do not bake secrets into an image.
python -m pytest -q
python -m build
python -m twine check dist/*CI tests Python 3.11 through 3.13, builds the distribution, checks package metadata, scans Git history for secrets, and scans the filesystem for high/critical vulnerabilities.
Do not put Nango keys, OAuth tokens, Infisical credentials, provider payloads, or customer data in issues, tests, fixtures, logs, or commits. Audit logs contain identities, tool names, outcomes, timing, and bounded operational metadata—not tokens, headers, arguments, or payloads.
See MIGRATION.md when upgrading from 1.x or 0.x.
MIT. Attribution is appreciated and preserved in the license.