Skip to main content
Glama

Digital.ai Agility MCP for Windows

A Python 3.12+ MCP server for Digital.ai Agility, formerly VersionOne. Runs over stdio using standalone FastMCP 4.1.3. Authentication comes exclusively from Windows Credential Manager, using the current Windows user's Generic Credentials.

Requires Windows 10/11 or Windows Server, Python 3.12+, and an Agility instance. uv is an optional installation/launch tool; ordinary Python also works. No Node.js, PowerShell, C# compiler, or native extension is required by the credential worker. It calls CredReadW, CredWriteW, CredDeleteW, and CredFree directly through Python ctypes in a short-lived process.

Offline ZIP for Python 3.14 on Windows x64

The agility-wincred-mcp-0.4.1-offline-win-x64-py314.zip bundle includes the server and every runtime dependency, including compiled extensions. Python itself is not included. The destination needs CPython 3.14.x, Windows x64 and access to your internal Agility server; no pip, uv, internet access, or installation is needed. This specific ZIP does not support other Python minor versions or architectures.

Extract the entire ZIP, open PowerShell in its folder, and run:

python -I .\agility-mcp.py --check-bundle
# Edit agility.json: set baseUrl and, if needed, restEndpoint.
python -I .\agility-mcp.py credentials set
python -I .\agility-mcp.py doctor
python -I .\agility-mcp.py serve

The launcher finds its bundled packages and agility.json relative to its own location. credentials set saves the token on the destination computer under the current Windows user; the ZIP contains no credentials. An existing matching credential on that computer can be reused. Use mcp-host.example.json for a host configuration with absolute Python and launcher paths. See the ZIP's README.txt for certificate settings and other details.

To rebuild on a connected Windows machine, using a Windows x64 Python 3.14 interpreter and uv:

python scripts/build_offline.py --python C:\Path\To\Python314\python.exe

The builder uses uv.lock, checks dependency download hashes, retains package licenses, and writes the ZIP and its SHA-256 under dist/. Its --offline option uses an already populated uv cache. Only the build machine needs uv. The bundled --check-bundle verifies file hashes, dependency compatibility, and native imports without network or credential access.

Related MCP server: Azure DevOps MCP Server

Quick start from this checkout

uv sync --locked
$env:AGILITY_BASE_URL = 'https://your-server/YourAgilityInstance'
uv run agility-mcp credentials set
uv run agility-mcp doctor
uv run agility-mcp credentials status

credentials set prompts for the access token without echoing it. Create the token in Agility's Member Applications/grant UI first; this server does not create grants. Repeating setup overwrites the same saved credential, allowing rotation. The default credential target is derived from the normalized instance URL; keep its path and case consistent.

The worker stores a Generic Credential with machine-local persistence for the current Windows user (Type=1, Persist=2), using UTF-16LE. You can also use Control Panel → Credential Manager → Windows Credentials → Add a generic credential with the exact target reported by credentials status. Token authentication accepts an arbitrary username; Basic authentication requires the Agility username. The secret limit is 2,560 bytes (1,280 UTF-16 code units).

Run the MCP host under the same Windows user as credential setup. A Linux, WSL, or remote process cannot read this user's Windows vault. To remove an entry, run uv run agility-mcp credentials delete with the same configuration.

Run with uvx

Version 0.4.1 is not published to PyPI. Build a wheel from this checkout:

uv build
uvx --from .\dist\agility_wincred_mcp-0.4.1-py3-none-any.whl agility-mcp --version
uvx --from .\dist\agility_wincred_mcp-0.4.1-py3-none-any.whl agility-mcp credentials set --base-url https://your-server/YourAgilityInstance
uvx --from .\dist\agility_wincred_mcp-0.4.1-py3-none-any.whl agility-mcp doctor --base-url https://your-server/YourAgilityInstance

Or use a full, reviewed Git commit SHA containing the Python migration:

uvx --from "git+https://github.com/foreman3/agility-server-mcp.git@<FULL_COMMIT_SHA>" agility-mcp serve --base-url https://your-server/YourAgilityInstance

Replace <FULL_COMMIT_SHA> with the exact revision you reviewed. Do not use an unpinned branch in a host configuration. python -m agility_mcp supports the same commands after installation.

MCP host configuration

A Windows MCP host that uses mcpServers can launch the built wheel:

{
  "mcpServers": {
    "agility": {
      "command": "uvx",
      "args": ["--python", "3.12", "--from", "C:\\path\\to\\agility_wincred_mcp-0.4.1-py3-none-any.whl", "agility-mcp", "serve"],
      "env": {
        "AGILITY_BASE_URL": "https://your-server/YourAgilityInstance"
      }
    }
  }
}

Use an absolute wheel path visible to the host. For a pinned source install, replace the --from argument with the Git URL above. For development use command: "uv" and args: ["run", "--project", "C:\\path\\to\\checkout", "agility-mcp", "serve"]. Ensure uv/uvx is on the host's PATH or specify the full executable path.

Migration from 0.3.0

Replace the Node/npx host launch command with uvx. JSON configuration keys, CLI flags, AGILITY_* variables, precedence, tool names, camelCase arguments, and result envelopes are preserved. Existing URL-derived credential targets and explicitly configured targets are unchanged; you do not need to re-enter existing credentials. Both credential implementations were checked with synthetic Unicode credentials in each direction.

Replace NODE_EXTRA_CA_CERTS with SSL_CERT_FILE pointing to a PEM bundle containing the certificate authorities needed by your instance. Python HTTPX uses its default CA bundle unless SSL_CERT_FILE or SSL_CERT_DIR overrides it; it does not automatically inherit Node's certificate settings. See HTTPX certificate configuration. HTTPX respects HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and NO_PROXY; configure NO_PROXY for local development fixtures. TLS verification is enabled by default and can be disabled with verifyTls: false.

Configuration

Configuration precedence: CLI flags → environment → optional JSON file → defaults. Pass --config C:\path\agility.json or set AGILITY_CONFIG. Unknown JSON keys are rejected to catch typos and misplaced secrets. No credential secret is accepted through CLI flags, environment variables, tool arguments, or config files.

JSON property

Environment variable

Default

baseUrl

AGILITY_BASE_URL

Required; include instance path

credentialTarget

AGILITY_CREDENTIAL_TARGET

agility-mcp: + first 32 hex chars of SHA-256(base URL)

authMode

AGILITY_AUTH_MODE

token; optional basic

restEndpoint

AGILITY_REST_ENDPOINT

rest-1.v1; optional rest-1.oauth.v1

enableWrites

AGILITY_ENABLE_WRITES

false

allowOperations

AGILITY_ALLOW_OPERATIONS

Empty; JSON array or comma-separated env/CLI list

timeoutMs

AGILITY_TIMEOUT_MS

30000 per HTTP attempt; range 100–300000

retries

AGILITY_RETRIES

2 additional read attempts; range 0–5

maxResponseBytes

AGILITY_MAX_RESPONSE_BYTES

4 MiB decompressed; range 1 KiB–32 MiB

maxConcurrency

AGILITY_MAX_CONCURRENCY

4; range 1–16

allowHttp

AGILITY_ALLOW_HTTP

false; development only

verifyTls

AGILITY_VERIFY_TLS

true; set to false to disable TLS certificate and hostname verification

The corresponding flags use kebab case, e.g. --base-url, --max-response-bytes, --enable-writes. Boolean environment variables accept exactly true or false; boolean CLI flags enable the option without a value.

Example configuration:

{
  "baseUrl": "https://your-server/YourAgilityInstance",
  "restEndpoint": "rest-1.oauth.v1",
  "enableWrites": true,
  "allowOperations": ["Close", "Reactivate"],
  "timeoutMs": 30000
}

Agility recommends bearer access tokens. For an instance configured with Windows Integrated Authentication, token-based REST access uses rest-1.oauth.v1. The credential source is the Windows vault; this server does not implement NTLM/Kerberos negotiation. Basic authentication is optional for deployments that support it; it is not supported for on-premises Windows Integrated Authentication or on-demand SSO. query.v1 has no configurable OAuth REST variant; if your deployment rejects it, use agility_list_assets, which uses the configured REST endpoint.

Use the application base URL, not /Default.aspx, /Account.mvc/Login, or an API endpoint URL. HTTPS is required unless explicitly allowing HTTP. For enterprise certificate authorities, set SSL_CERT_FILE to a trusted PEM certificate bundle as described in the migration section. HTTPX supports standard proxy environment variables.

For a self-signed server, you can disable TLS verification in your JSON configuration (including the offline bundle's agility.json):

{
  "baseUrl": "https://your-server/YourAgilityInstance",
  "verifyTls": false
}

The same setting is available as AGILITY_VERIFY_TLS=false or --verify-tls false, using the normal configuration precedence. It applies to MCP tools, doctor, and the offline launcher. Setting it to false disables certificate-chain and hostname checks; HTTPS traffic remains encrypted. Set it back to true to enable verification.

Tools

Tool

Purpose

agility_status

Configuration and credential presence; checkApi: true verifies a small authenticated REST query

agility_metadata

All asset types, or one type/attribute/operation definition

agility_list_assets

REST queries with select, where, text search, sort, paging, optional asOf

agility_get_asset

Read an OID with explicit selected fields; historical moment OIDs are supported

agility_get_item_detail

Detailed fields, schema metadata, hierarchy, upstream/downstream dependency graph, blockers, and cycle detection

agility_related_items

A resumable page of a metadata-verified relationship

agility_asset_history

Paged historical versions of one asset

agility_new_asset_template

Read defaults/template in an optional parent context

agility_query

Up to 10 read-only query.v1 JSON queries, including nested relations and variables

agility_create_asset

Create with scalar attributes and relationship changes; requires writes

agility_update_asset

Change scalar attributes and relationships; requires writes

agility_execute_operation

Lifecycle operations; requires writes and a nonempty exact operation allowlist

The first nine tools are always registered. Creation and update tools are only registered with writes enabled. The operation tool's schema contains only explicitly allowed operation names. To permit deletion, an operator must deliberately include Delete in allowOperations. Disabling writes removes the write tools entirely; the API client also enforces the settings.

Generic tools support your instance's standard and custom asset types instead of assuming a particular workflow. Common internal names: project = Scope, sprint = Timebox, backlog item = Story, defect = Defect, portfolio item = Epic, user = Member. Discover actual attributes and valid state values through metadata and queries. OIDs such as Story:1234 differ from display numbers such as S-01234.

Example: search a project's stories:

{
  "assetType": "Story",
  "select": ["Number", "Name", "Estimate", "Status.Name", "Owners.Name"],
  "where": "Scope='Scope:1000'",
  "sort": ["Number"],
  "pageSize": 100,
  "start": 0
}

REST list results contain assets, optional API total, pageSize, start, and nextStart. Pass nextStart as start until it is null. nextStart may require one final empty request if the API does not supply a total. Other read tools return normalized assets or API metadata. Attribute values remain strings as supplied by Agility XML; related OIDs appear under relations.

Parent IDs and names on item results

Portfolio and backlog item reads automatically add Super, Super.Name, and Super.Number to the requested fields, even when you select only Name. This applies to Epic, Story, Defect, TestSet, and the Workitem/PrimaryWorkitem collections. List, get, history, and query.v1 responses expose:

{
  "oid": "Story:1234",
  "parentId": "Epic:1000",
  "parentName": "Checkout experience",
  "parentNumber": "E-01000",
  "parentStatus": "resolved",
  "parent": {
    "oid": "Epic:1000",
    "id": "Epic:1000",
    "name": "Checkout experience",
    "number": "E-01000",
    "relation": "Super"
  }
}

Parent IDs are internal OIDs; the display number is separate. parentStatus distinguishes resolved, none (an explicitly empty relationship), unresolved (a parent OID is known but its name is unavailable), and unavailable (the API did not supply sufficient relationship data). Missing information is never represented as a known root. Selecting an historical item uses its historical projections; parent enrichment does not fetch current names for a historical read.

Agility's portfolio hierarchy is Super/Subs. Its Parent relation can describe a theme or another model-specific association and is preserved separately. query.v1 retains its array-of-arrays format and adds the normalized fields to item rows, including nested selections using Subs, SubsAndDown, Dependencies, Dependants, or Workitems. Those nested results are still subject to Agility's lack of nested paging. Relation-only references outside these recognized selections can have parentStatus: unavailable.

Create/update responses often contain only modified fields. After a successful write that returns one item, the client performs a separate read to resolve its parent. If that read fails, the write remains successful and hierarchyWarnings explains the missing enrichment. Do not repeat a successful write to repair its hierarchy output. Operation responses and new-item templates normalize whatever hierarchy data the API returns; lifecycle operations such as Delete can make the item unavailable for further reading.

Detailed item and dependency graph

Call agility_get_item_detail with a current OID:

{
  "oid": "Story:1234",
  "hierarchyDepth": 3,
  "dependencyDepth": 2,
  "pageSize": 50,
  "maxNodes": 150,
  "maxEdges": 750,
  "maxRequests": 100,
  "maxDurationMs": 30000,
  "includeMetadata": true
}

The result includes:

  • item: description, estimates, lifecycle/date fields, common single-valued context relations, custom scalar fields, and normalized parent information. Only fields found in instance metadata are selected. An explicit select replaces the default detail selection; parent fields are still added. Binary fields are excluded from defaults. Use agility_related_items for multivalue context such as Owners.

  • metadata: field definitions, required/read-only/custom/multivalue flags, related asset types, reciprocal relation names, supported operations, and inheritance. The reader handles singleton XML definitions and inherited fields, with an operation-local cache and an inheritance limit. includeMetadata: false suppresses returned schema data; discovery still uses metadata.

  • hierarchy.parent, hierarchy.ancestors, and hierarchy.descendants: item OIDs, names, numbers, parent data, and shortest-path distance from the root. Ancestors and descendants are traversed separately, so siblings are not mistaken for descendants.

  • dependencies.upstream: prerequisites needed by the requested item; dependencies.downstream: items that depend on the requested item. distance: 1 is direct; greater values are transitive. blockingIssues is separate from delivery dependencies.

  • impact.affected, impact.directDependants, and impact.blockingChains: affected downstream items and prerequisite paths. Every path is an ordered list of OIDs backed by explicit dependency edges in graph.edges. impact.cycles identifies dependency loops; impact.completeWithinRequestedDepth follows the traversal coverage flag. Use larger dependencyDepth to see farther along a chain.

  • graph.nodes, graph.edges, and graph.cycles: deduplicated nodes and directed edges. Hierarchy edges point parent → child; dependency edges point prerequisite → dependent. True cycles are reported, while shared dependencies in a diamond are not treated as cycles. At most 25 detected cycles per edge kind are reported.

  • coverage, warnings, and traversal: explicit availability, errors, paging, pending work, and the limits used. Always inspect these before treating the result as complete.

The reader recognizes instance-supported Dependencies/Dependants fields (and the explicit upstream/downstream naming variants when present). It verifies the relationship target and reciprocal in metadata, then queries the target collection with a reciprocal filter. This provides actual root-level API paging instead of downloading an unlimited nested relationship array. Missing or unverifiable metadata produces unsupported or unavailable coverage; permission/network failures produce error coverage. An empty result never silently stands in for a failed relationship query.

Detail option

Default

Range

hierarchyDepth

2

0–10; 0 disables hierarchy traversal

dependencyDepth

1

0–10; 0 disables dependency traversal

pageSize

50

1–200

maxNodes

100

1–500, including the root

maxEdges

500

1–5000

maxRequests

80

5–300 HTTP attempts, including metadata and retries

maxDurationMs

30000

1000–120000 across the entire operation

The traversal measures the complete serialized detail result against maxResponseBytes as it grows; the existing HTTP and tool result size limits remain enforced. A limit returns partial data with traversal.truncated: true, reasons, pending work, and resumable relationship pages. If metadata alone pushes the final result over the limit, it is omitted with metadataStatus: omitted_for_size. A root item or traversal bookkeeping that cannot fit returns an explicit size error; reduce select or raise the configured limit. A deadline reached before the root can be loaded returns a tool error. completeWithinRequestedDepth describes completion within the selected depths, not the entire connected graph. depthBoundaries lists nodes that were returned but not expanded farther.

For example, resume a partially fetched upstream dependency collection with agility_related_items:

{
  "oid": "Story:1234",
  "relation": "Dependencies",
  "pageSize": 50,
  "start": 50
}

The response includes nextStart and a ready-to-use continuation object with the next tool arguments. The same tool supports Super, Subs, Dependants, BlockingIssues, and other metadata-verified reciprocal relationships. A standalone related-items call verifies the source item is visible before querying its related collection.

Graphs reflect assets visible to the authenticated account. Reads are live and nontransactional; concurrent edits can change relationships while paging. Repeated rows or changed totals are flagged as pagination_changed. Dependency traversal follows explicit relationships; it does not invent inherited scheduling constraints between descendants of portfolio dependencies. Query ancestors and inspect their dependencies separately when analyzing those constraints.

Example: parameterized query with nested owners:

{
  "queries": [{
    "from": "Story",
    "select": ["Number", "Name", { "from": "Owners", "select": ["Name"] }],
    "filter": ["Scope=$project"],
    "with": { "$project": "Scope:1000" },
    "page": { "size": 50, "start": 0 }
  }]
}

Query results preserve the API array-of-arrays format. Every root query receives a default page of 100, capped at 1000. Page nested relationships by querying the related asset type separately; Agility does not support paging nested selections. Nested selections are limited to three levels. Batch size, nesting, and response bytes are bounded; these limits do not impose a server-side query execution budget on Agility.

Example: create a story:

{
  "assetType": "Story",
  "attributes": { "Name": "Add audit trail", "Estimate": 3 },
  "relations": [{ "name": "Scope", "action": "set", "targets": ["Scope:1000"] }]
}

Example: update owners without replacing the multivalue relationship:

{
  "oid": "Story:1234",
  "attributes": { "Description": "Updated description" },
  "relations": [
    { "name": "Owners", "action": "add", "targets": ["Member:20"] },
    { "name": "Owners", "action": "remove", "targets": ["Member:21"] }
  ]
}

set changes a single-valued relation and accepts zero or one target; an empty target list clears it. Use add/remove for multivalue relations. null writes an empty scalar value. Updates are partial, last-writer-wins changes without an optimistic concurrency guarantee. Read the asset first and verify it afterward when concurrent edits matter. Historical moment OIDs are rejected for mutations.

Reliability and security behavior

  • Credentials are loaded for each authenticated request, so rotation takes effect without restarting. Credential secrets necessarily exist briefly in process memory and the helper's pipe; they are never passed as process arguments or written to project files. Credential Manager protects storage, not processes already running as your Windows user.

  • Only fixed Agility endpoints under the configured base URL can be called. MCP tools cannot change the host, credential target, authentication mode, or HTTP method. Metadata is requested anonymously.

  • Redirects are blocked, including same-origin redirects. This prevents accidental credential forwarding and exposes incorrect instance paths or login redirects as errors.

  • Reads retry transport failures before a response and HTTP 429/502/503/504, with bounded exponential backoff/jitter or Retry-After (capped at 30 seconds). query.v1 POST is read-only and eligible for retries. Authentication, authorization, validation, and XML/JSON errors are not retried. Timeouts and failed response streams are not retried.

  • Creates, updates, and lifecycle operations are never retried automatically. A network failure can leave a write outcome unknown; check the asset before repeating it. There are no multi-asset transactions, bulk write tools, or automatic rollback.

  • Per-attempt timeouts include response streaming. MCP cancellation propagates to credential retrieval, HTTP requests, and retry waits. Credential retrieval has its own configured timeout and a 20-second helper safety cap. At most 64 requests can wait behind the configured concurrency limit. Each HTTP request body is capped at 1 MiB; responses are bounded while streaming.

  • XML values are escaped, identifiers validated, and DTD/entity declarations rejected. Server error bodies are not returned to the model or logs. Tool failures return MCP isError without crashing the connection.

  • Tool annotations identify read and destructive behavior. Agility's own permissions remain authoritative. Treat descriptions, comments, and other retrieved asset content as untrusted text.

Validation and development

uv sync --locked
uv run ruff check .
uv run ruff format --check .
uv run mypy
uv run pytest -q
uv run pytest integration/test_windows_credentials.py -q
uv build

Windows CI runs Python 3.12 and 3.14, Ruff, type checks, unit/contract tests, synthetic vault integration, wheel/sdist builds, packaged uvx launches, and installation from the exact Git commit. No publishing step is configured.

The normal suite uses synthetic HTTP responses, captured JavaScript schemas and semantic outputs, FastMCP in-memory sessions, cancellation tests, and a real stdio subprocess against a local HTTP fixture. The Windows integration tests create a unique synthetic Generic Credential, verify Unicode/rotation, authenticate a local stdio request, test worker cancellation, and delete the credential in finally. They never access existing tenant credentials. See baseline provenance.

To validate a real tenant, store its credential under your Windows user, then opt in to the read-only test:

$env:AGILITY_BASE_URL = 'https://your-server/YourAgilityInstance'
$env:AGILITY_LIVE_ITEM_OID = 'Story:1234'
$env:AGILITY_LIVE_TEST = '1'
uv run pytest integration/test_live_tenant.py -q -s

Set AGILITY_LIVE_EXPECT_PARENT_OID, AGILITY_LIVE_EXPECT_UPSTREAM_OID, or AGILITY_LIVE_EXPECT_DOWNSTREAM_OID to verify known relationships. AGILITY_LIVE_RELATION checks an additional paged relation. The test reads metadata, the item, and its bounded detail graph; it never changes Agility data. It reports incomplete traversal reasons when permissions or deployment metadata prevent discovery.

No live Agility tenant is bundled. Run doctor against your instance to verify its token, endpoint choice, permissions, certificates, and deployment-specific behavior. Metadata and workflows differ across versions and installations. Attachment uploads/downloads, ActivityStream, tags endpoints, full administrative workflows, HTTP hosting, and automatic token grant creation are outside this version's scope.

API references

This is an independent integration, not an official Digital.ai product.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for the Delinea Secret Server and Platform APIs, enabling AI agents to manage secrets, users, groups, folders, roles, and access requests through natural language commands.
    50
    MIT
  • F
    license
    A
    quality
    C
    maintenance
    Enables users to connect to Salesforce and perform CRUD operations, run SOQL/SOSL queries, and manage records through a lightweight MCP server with built-in safety gates for writes.
    9
    1
    -
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI coding agents to read TeamStorm tasks, comments, attachments, and links, and to perform limited write operations such as adding comments and updating task names, descriptions, or statuses through MCP.
    15
    3
    MIT