Skip to main content

keycardai-fastmcp

FastMCP integration for Keycard OAuth: protect FastMCP servers with Keycard authentication and run delegated OAuth 2.0 token exchange (RFC 8693) for downstream APIs.

This is the canonical home for the integration. The old name, keycardai-mcp-fastmcp, is retired; its final release (0.21.0) remains on PyPI so existing pins keep resolving.

Installation

pip install keycardai-fastmcp

Quick Start

from fastmcp import FastMCP
from keycardai.fastmcp import AccessContext, AuthProvider

auth_provider = AuthProvider(
    zone_id="abc1234",
    mcp_server_name="My Server",
    mcp_base_url="http://localhost:8000",
)

mcp = FastMCP("My Server", auth=auth_provider.get_remote_auth_provider())

@mcp.tool()
async def call_external_api(
    query: str,
    access: AccessContext = auth_provider.grant("https://api.example.com"),
):
    token = access.access("https://api.example.com").access_token
    return f"Results for {query} (token starts with {token[:8]})"

Declaring the grant as a typed parameter default injects the populated AccessContext per request; the parameter never appears in the tool's input schema. Exchange failures are recorded on the AccessContext (check access.has_errors() / access.get_errors()), never raised. Granting multiple resources is all-or-nothing: if any exchange fails, the context carries that resource's error and no tokens.

If you lint with flake8-bugbear or Ruff's B008 rule (function call in argument default), exempt your tool modules: the call-in-default is the intended spelling here, the same pattern as FastAPI's Depends. In pyproject.toml:

[tool.ruff.lint.per-file-ignores]
"src/my_server/tools/*.py" = ["B008"]

Migrating from the decorator form

The decorator form (@auth_provider.grant(...) above the tool) still works from the same object. Reading the result via ctx.get_state("keycardai") is deprecated and emits a DeprecationWarning; helpers that only hold the FastMCP Context can use await AccessContext.from_context(ctx) instead.

The warning fires once per tool, at decoration time (module import). If your test or CI setup escalates warnings to errors (-W error, filterwarnings = ["error"] in pytest config), importing a server module that still uses the old form will raise instead of warn. Either migrate the tools to the injected-parameter form, or allow this warning explicitly:

filterwarnings = ["error", 'default:Tool .* uses the grant decorator:DeprecationWarning']

Configuration from the environment

AuthProvider reads its zone and application credential from the environment when they are not passed explicitly.

Zone: set KEYCARD_ZONE_URL to the full zone URL. KEYCARD_ZONE_ID and KEYCARD_BASE_URL still work but emit a DeprecationWarning; migrate as follows:

Deprecated Canonical replacement
KEYCARD_ZONE_ID="abc1234" KEYCARD_ZONE_URL="https://abc1234.keycard.cloud"
KEYCARD_ZONE_ID="abc1234" + KEYCARD_BASE_URL="https://custom.example.com" KEYCARD_ZONE_URL="https://abc1234.custom.example.com"

Application credential: discovery is delegated to keycardai.oauth.server.discover_credential. KEYCARD_APPLICATION_CREDENTIAL_TYPE selects client_secret, workload_identity or web_identity (eks_workload_identity is accepted as a legacy alias). Without a selector, exactly one source may be configured: KEYCARD_CLIENT_ID + KEYCARD_CLIENT_SECRET, an injected workload token file (AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, AWS_WEB_IDENTITY_TOKEN_FILE, AZURE_FEDERATED_TOKEN_FILE or KEYCARD_EKS_WORKLOAD_IDENTITY_TOKEN_FILE), or KEYCARD_WEB_IDENTITY_KEY_STORAGE_DIR. More than one source with no selector fails at startup with an ambiguity error naming the selector as the remedy.

Testing

Fake delegated access without patching internals:

from keycardai.fastmcp.testing import mock_access_context

with mock_access_context(access_token="fake_token"):
    ...  # grants resolve to an AccessContext serving fake_token

The bare access_token form serves the token for any resource, so it will not catch a mistyped resource URL in an access(...) call. Pass resource_tokens={...} when the test should enforce which resources the tool reads; resources outside the dict raise ResourceAccessError, matching production.

Migration from keycardai-mcp-fastmcp

The keycardai-mcp-fastmcp package is retired. Its final release, 0.21.0, stays on PyPI so existing pins keep resolving: from keycardai.mcp.integrations.fastmcp import AuthProvider emits a DeprecationWarning pointing here and returns the same class. New code should depend on keycardai-fastmcp and import from keycardai.fastmcp.

Metadata

Release files for keycardai-fastmcp 0.7.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for keycardai-fastmcp 0.7.4
File Size Uploaded Provenance Actions
keycardai_fastmcp-0.7.4.tar.gz 166.5 kB Without provenance Details for keycardai_fastmcp-0.7.4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for keycardai-fastmcp 0.7.4
File Interpreter ABI Platform Actions
keycardai_fastmcp-0.7.4-py3-none-any.whl Python 3 none any Details for keycardai_fastmcp-0.7.4-py3-none-any.whl

Total release size: 189.5 kB

Release files / keycardai_fastmcp-0.7.4.tar.gz

Download URL keycardai_fastmcp-0.7.4.tar.gz
Size 166.5 kB
Tags Source
SHA-256 checksum
How to use checksums
eacb9e97c046749456b99f5c8e390b1a3de7b058d48b508dc8baf7b91699b781
BLAKE2b-256 checksum
How to use checksums
4bfe9efe0b4a1f60799c09d7e8a5a66ca80109b88f6ef70e6f690ed668062f13
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / keycardai_fastmcp-0.7.4-py3-none-any.whl

Download URL keycardai_fastmcp-0.7.4-py3-none-any.whl
Size 23.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
026f6f8b3b1b5c5c17e7bdd477ff00a4a2e6fba3524e0a4e48c7098b0b26f89f
BLAKE2b-256 checksum
How to use checksums
4a8a246cdea9434d00f47ceab0837d5ede8f96a555d9b8f6d7d8f251f8ac3a2c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for keycardai-fastmcp 0.7.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page