Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,11 @@ jobs:
run: uv sync --all-extras --all-packages

- name: Build package
# Build by path, not --package: `uv build --package` resolves against
# workspace.members, and packages/fastmcp + packages/mcp-fastmcp are
# deliberately excluded from the workspace (see ECO-198).
run: |
uv build --package ${{ needs.detect-package.outputs.package }}
uv build --out-dir dist "${{ needs.detect-package.outputs.package-dir }}"

- name: Publish to PyPI
run: |
Expand Down
17 changes: 13 additions & 4 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ dev-setup:
uv run pre-commit install
uv sync --all-extras --all-packages

# Build the project
# Build the project. packages/fastmcp and packages/mcp-fastmcp sit outside the
# uv workspace (they hold mcp<2.0; see ECO-198), so they sync separately.
build:
uv sync --all-packages
cd packages/fastmcp && uv sync --extra test
cd packages/mcp-fastmcp && uv sync --extra test

# Run tests for all packages
test: build
just test-package oauth
just test-package starlette
just test-package mcp
just test-package fastmcp
just test-package mcp-fastmcp
just test-package a2a

Expand All @@ -23,13 +27,18 @@ test-package PACKAGE:
test-file PACKAGE FILE:
cd packages/{{PACKAGE}} && uv run --extra test pytest tests/{{FILE}} -v

# Run tests with coverage enforcement. mcp sits at 60% because well-tested server
# primitives moved to oauth/starlette, leaving the under-tested client integrations
# (CrewAI, LangChain, OpenAI) as the dominant share of what remains.
# Run tests with coverage enforcement. mcp stays at 60%, but the denominator it
# measures grew: 2679 statements against ~2500 before, because all four
# *_agents.py client integrations are now imported by
# tests/.../test_tool_schema_reads.py and so are counted. Dropping the agent
# frameworks alone would have shrunk it to 2036 and inflated the percentage to
# ~75 on less measured code; that test is what keeps the gate honest. Headroom
# is thin (60.88% actual) -- if it dips, add coverage rather than lowering this.
test-coverage: build
cd packages/oauth && uv run --extra test pytest tests/ -v --cov=src --cov-report=term-missing --cov-fail-under=70
cd packages/starlette && uv run --extra test pytest tests/ -v --cov=src --cov-report=term-missing --cov-fail-under=55
cd packages/mcp && uv run --extra test pytest tests/ -v --cov=src --cov-report=term-missing --cov-fail-under=60
cd packages/fastmcp && uv run --extra test pytest tests/ -v --cov=src --cov-report=term-missing --cov-fail-under=60
cd packages/mcp-fastmcp && uv run --extra test pytest tests/ -v --cov=src --cov-report=term-missing --cov-fail-under=70
cd packages/a2a && uv run --extra test pytest tests/ -v --cov=src --cov-report=term-missing --cov-fail-under=55

Expand Down
18 changes: 17 additions & 1 deletion packages/fastmcp/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ dependencies = [
"httpx>=0.27.2",
"keycardai-oauth>=0.7.0",
"fastmcp>=3.1.0",
"keycardai-mcp>=0.15.0",
# Pinned to the 0.27.x line, both ends load-bearing. fastmcp 3.x pins
# mcp<2.0, so this package needs a keycardai-mcp that agrees. 0.27.0 is the
# first release carrying "mcp<2.0"; 0.26.0 and earlier declare an unbounded
# "mcp>=1.13.1" and resolve onto mcp 2.0, which fails to import. The upper
# bound excludes the mcp 2.0 line this PR starts. Move both ends together
# with the fastmcp 4.x bump (ECO-198).
"keycardai-mcp>=0.27,<0.28",
]
keywords = ["fastmcp", "mcp", "model-context-protocol", "oauth", "token-exchange", "authentication", "keycard"]
classifiers = [
Expand All @@ -35,6 +41,8 @@ classifiers = [
test = [
"pytest>=8.4.1",
"pytest-asyncio>=1.1.0",
"pytest-cov>=6.2.1",
"requests>=2.32.0",
]

[project.urls]
Expand All @@ -43,6 +51,14 @@ Repository = "https://github.com/keycardai/python-sdk"
Documentation = "https://docs.keycardai.com"
Issues = "https://github.com/keycardai/python-sdk/issues"

[tool.uv.sources]
# Only keycardai-mcp comes from the index: it is on mcp>=2.0 and this package is
# on mcp<2.0, so the local copy is genuinely unusable here. Everything else is
# path-linked so a breaking change in a sibling still fails this package's CI.
keycardai-oauth = { path = "../oauth", editable = true }
# keycardai-starlette stays on the index: it is a transitive dependency via
# keycardai-mcp, and tool.uv.sources only redirects direct dependencies.

[build-system]
requires = ["hatchling", "uv-dynamic-versioning"]
build-backend = "hatchling.build"
Expand Down
Loading
Loading