v1.1.0
Added
-
Release workflow: a
vX.Y.Ztag verifies the tag against
core/version.pyand a CHANGELOG section (scripts/release_notes.py),
runs the tests, buildslinux/amd64+linux/arm64, pushes
ghcr.io/jersonmartinez/mcp-github-projects(X.Y.Z,X.Y,latest) and
publishes the GitHub release.core/version.pyis the single source of the
version;server_inforeports it and the MCP handshake advertises it. See
docs/RELEASING.md. -
Documentation drift guard + invoke-every-tool test (issue #36).
docs/TOOLS.mdis generated from the live registry by
scripts/gen_tool_docs.py(name, access tier, capabilities, summary);
tests/test_tool_docs.pyfails when it is stale, when a tool is missing
from it or has no description, and invokes every registered tool through
a real FastMCP client with schema-derived arguments against injected fakes,
requiring a structured{"ok": ...}envelope from each. -
Board structure tools (issue #26):
set_field_options(plan by default;
preserves option ids so items keep their values, keeps unlisted options
unlessremove_missing+confirm),list_project_views,
create_project_view. The public API gainedupdateProjectV2Field
single-select options andcreateProjectV2View(verified by introspection),
so the earlier "Status columns cannot be provisioned" limit no longer holds. -
GH_PROJECT_BACKEND_ASSIGNEE/GH_PROJECT_FRONTEND_ASSIGNEEsettings for
suggest_issue_assignee. -
GitHub Actions / checks tools (issue #32, epic #5) in
tools/ci/actions.py:
read —list_workflows,list_workflow_runs,get_workflow_run(jobs +
failed steps),get_pr_checks(check runs + commit statuses on the PR head,
overall= passed/failed/pending/none),get_job_logs(bounded tail,
ANSI escapes stripped, secrets redacted); write —rerun_workflow_run
(failed jobs or whole run) anddispatch_workflow(workflow_dispatchwith
≤ 10 string inputs). New capabilitiesactions.read/actions.write
classify them forMCP_ACCESS_LEVEL;owner/repooverrides honour
GH_PROJECT_SCOPE_LOCK. Lets the MCP verify a PR's CI withoutgh pr checks. Tool count: 119 → 126 atfull. -
Access levels (
MCP_ACCESS_LEVEL) —read|write|full, default
write(issue #34, epic #33). Governs which tools the server registers:
readexposes only read-only tools,writekeeps today's create/update/
close/archive surface (nothing removed), andfulladditionally exposes
five permanent-delete tools. Every registered tool is classified read/write/
delete incore/access.py(derived fromcore/capabilities.py, the single
source of truth), and a test asserts every registered tool is classified.
The variable isMCP_-prefixed (parity with mcp-monday-projects). -
Permanent-delete tools —
delete_project_item(deleteProjectV2Item),
delete_issue(deleteIssue),delete_issue_comment,delete_label,
delete_milestone. Exposed ONLY atMCP_ACCESS_LEVEL=full; each refuses
unless called withconfirm:true, stating the deletion is permanent and
pointing to the reversible alternative (close_issue,archive_project_item,
close_milestone, …). Tool count atfull: 114 → 119. -
Scope lock (
GH_PROJECT_SCOPE_LOCK) —true|false, defaultfalse
(parity with mcp-monday-projects'MONDAY_WORKSPACE_ID). Whentrue, every
tool is confined to the configuredGH_PROJECT_ORG_NAME/
GH_PROJECT_REPO_NAME/GH_PROJECT_PROJECT_NUMBER; a call targeting any
other owner/repo/project is refused with a typedScopeLockErrornaming the
variable, before any mutation. Repository/project creation is disabled while
the lock is on. -
server_infodiagnostics tool — reports the effective access level,
scope lock, tool-exposure counts, and configured target (no credentials). -
.env.examplegains boxed Access level and Scope lock sections plus a
commented Access level examples block with read-only / write / full presets. -
sync_closed_items_to_done— board-reconciliation tool that moves items whose
linked issue/PR is CLOSED or MERGED to the Done column (skips items already in a
terminal column). Supportsdry_runpreview andissue_or_pr_numberscoping.
GitHub does not auto-advance a card to Done when its PR merges, so cards
otherwise linger in In Progress; this tool reconciles them in bulk.
Tool count 104 → 105.
Changed
-
make buildnow tagsmcp-github-projects:latest, the name every
README/SETUP example and client configuration uses (and the GHCR package
name). The Makefile alone usedgithub-project-mcp:latest; retag an old
local image withdocker tag github-project-mcp:latest mcp-github-projects:latest. -
Docs audit (issue #37): removed leftovers from the project this server
was extracted from (aprofiles/factib.envhint that pointed to a missing
file, afactib_backendcontainer, anapp.mcp.github_projectmodule path,
an IDE-specific architecture diagram, personal logins and dated sprint names
in examples); USAGE now defers the full list to TOOLS.md and documents that
Status/Priority values are read from the board; CAPABILITIES replaces its
hand-maintained (and already drifted) per-tool matrix with the generated
one; GRAPHQL_REFERENCE lists the new operations; README drops a link to a
wiki that does not exist; AGENTS no longer names pointer files that are not
in the repo; the unusedscripts/check_sync.sh(compared against an
embedded copy in another repository) is removed. -
Uniform tool-argument convention (issue #4). Every tool now accepts
flat arguments ({"issue_number": 1}) and still unwraps a legacy
{"params": {...}}wrapper, so clients no longer need to know per tool
which shape to send. The advertised input schema is the flat one (real
fields andrequiredlist) plus an optional deprecatedparamsobject.
Validation still runs against each tool's own models (types, constraints,
model validators unchanged); failures name the field and the expected
shape. Applied centrally incore/arguments.pyat registration.
scripts/mcp_call.pysends flat args by default (--wrapfor the legacy
form;--flatis a no-op). -
Architecture: HARDENING_200 items 6-8 (issue #35, epic #33), no change to
any tool name or input schema (byte-identicaltools/listat every access
level):core/factory.py::ServiceFactoryis now the single construction point for
GraphQLClient,GHCLIClient,CacheManagerand the services. It replaces
69 inline constructions in 23 tool modules; a test fails if a tool builds
one inline again. Tests inject fakes withuse_service_factory(...).core/protocols.pyadds theGraphQLExecutorandGHCLIRunner
protocols; services and helpers are typed against them, and a contract test
checks the real clients still match.core/context.pyruns every tool call in aRequestContext. Its
correlation_idprefixes each stderr log line of the call and is returned
as the newToolError.correlation_idfield.
-
server.pyregistration is now gated byMCP_ACCESS_LEVEL: only tools
exposed at the configured level are registered.scripts/count_tools.py
seeds a dummy target +MCP_ACCESS_LEVEL=fullso the structural count stays
deterministic and env-independent (verifies the full 119-tool surface). -
sync_closed_items_to_donenow scans the board exhaustively — it pages the
entire board pastGH_PROJECT_MAX_ITEMS(via the new
ProjectService.list_all_items), so boards with more than 200 cards are fully
reconciled in a single call, including theissue_or_pr_numberscope. The
previousscan_capped/max_itemsresponse fields are removed (no longer
meaningful)._fetch_all_itemsgains anexhaustiveflag with a large safety
ceiling. -
_ITEMS_FRAGMENT(list-items GraphQL) now selects the contentstateand a
PullRequestblock, andProjectItemgains acontent_statefield
(OPEN/CLOSED/MERGED). PR-typed items are now parsed instead of skipped.
Fixed
-
Status option matching —
move_to_done,move_to_trashand
move_to_statusnow resolve a bare name against an emoji-prefixed option
(Done→✅ Done) when the match is unique; before, boards with emoji
options rejectedmove_to_doneoutright. -
60 capability-suite tools advertised an empty description to MCP
clients; each now has an accurate one-line summary (written against the
implementation, e.g.find_stale_issues= no assignee or no update
timestamp). -
suggest_issue_assigneehardcoded two personal logins; it now reports
the area and suggests only a configured login. -
Plan-only helpers were classified as write (
project_set_default_*,
project_bulk_*_by_filter,project_sync_issue_metadata,
project_import_markdown,auto_triage_issue): they never mutate, so they
are read tools and available atMCP_ACCESS_LEVEL=read. -
Clean fail-fast on misconfiguration (issue #3). Starting the server with
missing project context or an invalid setting no longer ends in a pydantic
traceback: bothpython server.pyandpython -mprint one
Configuration error: …line to stderr and exit with code2(distinct
from1, auth failure). Covered by subprocess tests in
tests/test_fail_fast.py.