Skip to content
Merged
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
14 changes: 14 additions & 0 deletions docs-web/content/docs/developer-mcp-tools.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,20 @@ Every tool requires `runtimeRoles: ["project_manager"]` and is enabled by defaul
| `manage_preview` | `list_sessions`, `start_session`, `stop_session`, `rebuild_session`, `remove_session`, `get_logs`, `get_url`, `get_script`, `update_script` |
| `manage_telemetry` | `get_project_stats_snapshot`, `get_project_execution_snapshot`, `list_execution_invocations`, `list_execution_invocation_messages`, `list_sprint_runs`, `list_task_dispatches` |

### Sprint issue imports

`manage_sprints` action `import_issues` accepts `provider` values `github`, `gitlab`, `jira`, `notion`, `asana`, and `linear`.

- GitHub and GitLab require saved effective `git.githubToken` / `git.gitlabToken` settings.
- Jira requires saved Jira host, email, API token, and usually a default project key.
- Notion requires `notion.apiToken`; optional `databaseId` narrows page/database imports.
- Asana requires `asana.apiToken` plus `workspaceId` for workspace search or `providerProjectId` for project task fallback.
- Linear requires `linear.apiToken`; optional `teamId`, `teamKey`, and `providerProjectId` narrow issue search.

Common import fields include `search`, `state`, `status`, `labels`, `assignee`, `issueKeys`, `issueNumbers`, `issueRefs`, `externalIds`, `includeConversation`, `limit`, `sprintId`, `attachToSprint`, and `planAfterImport`. Use `externalIds` for explicit Notion page/database ids, Asana task gids, and Linear issue ids or identifiers.

Notion, Asana, and Linear imports are read-only: Code UX searches, fetches prompt context, attaches linked-source records, and can plan from imported scope, but it does not close, complete, archive, or transition those provider items.

For the full per-action payloads and return shapes, see [Management actions](/docs/developer-management-actions).

## Approval handshake (destructive actions)
Expand Down
4 changes: 3 additions & 1 deletion docs-web/content/docs/user-dashboard-sprints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ Importing is the recommended way to template sprints across projects when [Quick

You can also import linked sprint scope from configured external systems. GitHub and GitLab imports use the saved effective `git.githubToken` and `git.gitlabToken` settings. Jira imports use the existing Jira settings block: site URL, email, API token, default project, import transition, close transition, and Jira auto-close behavior.

Notion, Asana, and Linear imports are API-backed and read-only. Notion uses `notion.apiToken` plus an optional `databaseId`, Asana uses `asana.apiToken` plus `workspaceId` or project fallback, and Linear uses `linear.apiToken` plus optional `teamId`, `teamKey`, or project filters. These importers can search, fetch readable body/comment context, attach linked scope to a sprint, and plan from that imported scope; they do not archive Notion pages, complete Asana tasks, transition Linear issues, or close those external items.

The shared settings model also supports Notion, Asana, Linear, Miro, Lucid, Figma, and Mural connection blocks. These provider blocks store enablement, token/secret, base URL, workspace/team/project identifiers, database/board/document/file identifiers, and a default search limit. They are saved and resolved through the same system → project → sprint settings hierarchy as other sprint integrations.

Linked sprint records preserve numeric issue numbers for GitHub, GitLab, and Jira. Non-numeric external objects are stored with an `externalId`, `sourceKind`, and `sourceProvider`, so future importer flows can attach pages, boards, documents, files, tasks, and canvas objects without inventing fake issue numbers.
Linked sprint records preserve numeric issue numbers for GitHub, GitLab, and Jira. Non-numeric external objects are stored with an `externalId`, `sourceKind`, and `sourceProvider`, so Notion pages/databases, Asana tasks, Linear issues, and future board/document/file/canvas importers can attach scope without inventing fake issue numbers.

## Sprint settings overrides

Expand Down
16 changes: 13 additions & 3 deletions docs/dashboard/sprint-imports.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Sprint Imports

Sprint imports support three production paths from the Sprints page: structured markdown bundles, GitHub/GitLab issue imports, and Jira issue imports.
Sprint imports support production paths from the Sprints page and MCP: structured markdown bundles, GitHub/GitLab issue imports, Jira issue imports, and read-only linked-scope imports from Notion, Asana, and Linear.

Internal MCP clients use the same importer services through `manage_sprints` action `import_issues`. For payload examples covering search-only imports, assigned-work searches, explicit Jira keys, explicit GitHub/GitLab issue numbers, sprint attachment, and plan-after-import flows, see [MCP Tools and Contracts: `manage_sprints import_issues`](../mcp/tools-and-contracts.md#manage_sprints-import_issues).
Internal MCP clients use the same importer services through `manage_sprints` action `import_issues`. For payload examples covering search-only imports, assigned-work searches, explicit Jira keys, explicit GitHub/GitLab issue numbers, explicit Notion/Asana/Linear external IDs, sprint attachment, and plan-after-import flows, see [MCP Tools and Contracts: `manage_sprints import_issues`](../mcp/tools-and-contracts.md#manage_sprints-import_issues).

## Markdown Import

Expand Down Expand Up @@ -71,12 +71,22 @@ Repository issues have two import modes. `Import as linked issues` creates linke
Issue import uses the saved integration tokens:
- GitHub: system/project effective `git.githubToken`, usually configured in Settings -> Integrations.
- GitLab: system/project effective `git.gitlabToken`, usually configured in Settings -> Integrations or seeded from `GITLAB_TOKEN` / `GLAB_TOKEN` host hints.
- Notion: system/project effective `notion.apiToken`; `databaseId` can narrow search or explicitly import a database.
- Asana: system/project effective `asana.apiToken`; workspace search uses `workspaceId`, while project fallback uses `projectId`.
- Linear: system/project effective `linear.apiToken`; `teamId`, `teamKey`, and `projectId` can narrow issue search.

When the GitHub token is empty, GitHub issue search, issue context loading, and auto-close fail with a token-required error. Code UX does not fall back to local `gh` or `glab` CLI authentication for dashboard or MCP importer workflows; Docker auth-copy mount settings help worker containers, but issue search, explicit import, linked sprint attachment, planning imports, and close operations need saved GitHub/GitLab tokens.

Notion, Asana, and Linear importer workflows use direct provider APIs through `fetch` and require saved tokens before any network request is made. They are read/attach only: Code UX searches, fetches readable context, persists local linked-source records, enriches sprint prompts, and can plan from that imported scope, but it does not archive Notion pages, complete Asana tasks, transition Linear issues, or close those external items.

Provider-specific search behavior:
- Notion uses `POST https://api.notion.com/v1/search` with `Authorization: Bearer` and `Notion-Version`, maps pages and databases, and reads page/database block children into prompt markdown when blocks are readable.
- Asana uses `GET https://app.asana.com/api/1.0/workspaces/{workspace_gid}/tasks/search` for workspace task search and falls back to project tasks when a project id is supplied. When conversation context is requested, task stories/comments are appended to prompt markdown.
- Linear uses `POST https://api.linear.app/graphql` for issue search/filter queries and explicit issue fetches. Results include description, labels, state, team/project, assignee, URL, and comments when conversation context is requested.

## Project-Management And Canvas Integration Settings

Code UX now carries shared typed settings for additional importer providers: Notion, Asana, Linear, Miro, Lucid, Figma, and Mural. These settings are available at system scope, project scope, sprint effective-settings resolution, and the dashboard type contracts. Jira continues to use the existing `jira` settings block, and GitHub/GitLab continue to use `git.githubToken` and `git.gitlabToken`.
Code UX carries shared typed settings for additional importer providers: Notion, Asana, Linear, Miro, Lucid, Figma, and Mural. Notion, Asana, and Linear have API-backed sprint importers today. Miro, Lucid, Figma, and Mural currently have settings and linked-source persistence contracts but no API-backed sprint importer in this flow yet. Jira continues to use the existing `jira` settings block, and GitHub/GitLab continue to use `git.githubToken` and `git.gitlabToken`.

Each new provider settings block stores only strings and a bounded numeric search limit:

Expand Down
67 changes: 64 additions & 3 deletions docs/mcp/tools-and-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -437,15 +437,19 @@ For sprint create/update calls:

### `manage_sprints import_issues`

`manage_sprints` action `import_issues` is the MCP contract for Jira, GitHub, and GitLab issue importer access. Internal MCP clients use it for search-only discovery, assigned-work searches, explicit ticket imports, linked sprint issue attachment, and optional planning after import.
`manage_sprints` action `import_issues` is the MCP contract for GitHub, GitLab, Jira, Notion, Asana, and Linear importer access. Internal MCP clients use it for search-only discovery, assigned-work searches, explicit ticket or external-object imports, linked sprint issue attachment, and optional planning after import.

Provider requirements:
- GitHub imports require a saved effective `git.githubToken` in system or project settings.
- GitLab imports require a saved effective `git.gitlabToken` in system or project settings.
- Jira imports require Jira integration settings: host/site URL, account email, API token, and usually a default project key.
- Notion imports require a saved effective `notion.apiToken`. `databaseId` can narrow page search or explicitly import a database.
- Asana imports require a saved effective `asana.apiToken` plus either `workspaceId` for workspace task search or `providerProjectId` / `asana.projectId` for project task fallback.
- Linear imports require a saved effective `linear.apiToken`. `teamId`, `teamKey`, and `providerProjectId` can narrow issue search when configured or supplied.
- Importer workflows do not fall back to local CLI authentication. A locally authenticated `gh`, `glab`, or Git remote is not enough for MCP issue search, explicit import, sprint attachment, or planning import paths.
- Notion, Asana, and Linear imports are read/attach only. Code UX does not transition, complete, close, or otherwise mutate those external work items.

Search/import callers can provide `provider` (`github`, `gitlab`, or `jira`), `repository`, `hostDomain`, `projectKey`, `search`, `state`, `status`, `labels`, `assignee`, `assigneeText`, `issueKeys`, `issueNumbers`, `issueRefs`, `includeConversation`, `limit`, and optional sprint attachment fields. `sprintId` and `attachToSprint` represent sprint attachment intent. `planAfterImport`, `autoStart`, `planningAgentPresetId`, `replan`, and `overrides` represent optional planning intent after import.
Search/import callers can provide `provider` (`github`, `gitlab`, `jira`, `notion`, `asana`, or `linear`), `repository`, `hostDomain`, `workspaceId`, `providerProjectId`, `externalProjectId`, `asanaProjectId`, `linearProjectId`, `teamId`, `teamKey`, `databaseId`, `projectKey`, `search`, `state`, `status`, `labels`, `assignee`, `assigneeText`, `issueKeys`, `issueNumbers`, `issueRefs`, `externalIds`, `includeConversation`, `limit`, and optional sprint attachment fields. `sprintId` and `attachToSprint` represent sprint attachment intent. `planAfterImport`, `autoStart`, `planningAgentPresetId`, `replan`, and `overrides` represent optional planning intent after import.

Search-only GitHub example:

Expand Down Expand Up @@ -491,6 +495,50 @@ Assigned-to-me Jira example:
}
```

Search-only Notion example:

```json
{
"action": "import_issues",
"projectId": "project-123",
"provider": "notion",
"databaseId": "notion-database-id",
"search": "roadmap acceptance criteria",
"limit": 10
}
```

Search-only Asana example:

```json
{
"action": "import_issues",
"projectId": "project-123",
"provider": "asana",
"workspaceId": "asana-workspace-gid",
"providerProjectId": "asana-project-gid",
"search": "checkout import",
"includeConversation": true,
"limit": 20
}
```

Search-only Linear example:

```json
{
"action": "import_issues",
"projectId": "project-123",
"provider": "linear",
"teamKey": "ENG",
"state": "In Progress",
"labels": ["import"],
"search": "checkout",
"includeConversation": true,
"limit": 20
}
```

Explicit Jira key example:

```json
Expand Down Expand Up @@ -532,6 +580,18 @@ Explicit GitHub issue number example:
}
```

Explicit external object example:

```json
{
"action": "import_issues",
"projectId": "project-123",
"provider": "notion",
"externalIds": ["notion-page-id"],
"includeConversation": false
}
```

Attach imported issues to an existing sprint:

```json
Expand Down Expand Up @@ -572,12 +632,13 @@ Attach imported issues and run planning after the sprint goal is enriched:

Result shape:
- Search mode returns `mode: "search"` and populates `searchedIssues` with lightweight normalized issue summaries.
- Explicit-reference mode returns `mode: "explicit"` and populates `importedContexts` with prompt contexts that can include full issue body and conversation text.
- Explicit-reference mode returns `mode: "explicit"` and populates `importedContexts` with prompt contexts that can include full issue body and conversation text. For Notion, Asana, and Linear, explicit imports use `externalIds`.
- When `sprintId` is supplied and `attachToSprint` is not `false`, the response includes persisted `linkedIssues` metadata records and the updated `sprint`.
- When `planAfterImport` is `true`, the response includes the optional `planning` result from sprint planning. `planAfterImport` requires `sprintId` because planning runs against an existing sprint.

Persistence and prompt behavior:
- `issueKeys` and Jira-style refs such as `OPS-123` resolve through Jira. `issueNumbers` and refs such as `#42` or `!42` resolve through GitHub/GitLab when `repository` and `hostDomain` are provided or inferable from the project.
- `externalIds` resolve through Notion page/database fetches, Asana task fetches, or Linear issue fetches. Search results and explicit contexts normalize to linked-source records with `externalId`, `sourceKind`, stable display keys, source URL, preview text, metadata, and prompt markdown when readable provider content is available.
- Full issue body and comment/conversation text are merged into the sprint goal under `## Linked Issues` before planning so the Planning agent receives the complete context.
- Linked issue persistence stores metadata only: provider, repository or project key, issue key/number, title, labels, assignees, status, source URL, and related tracking fields. Full remote issue bodies and comments remain prompt-only data and are not stored in linked issue rows.
- Issue search and import are not destructive actions. Sprint deletion remains approval-gated.
Expand Down
15 changes: 12 additions & 3 deletions src/contracts/mcp-tool-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,34 @@ export const TOOL_DEFINITIONS = [
goal: { type: "string", description: "Optional for create and update." },
goalMarkdown: { type: "string", description: "Alias for goal. Optional for create and update." },
originalPrompt: { type: "string", description: "Optional source prompt for create and update." },
status: { type: "string", description: "Optional sprint status for create and update, or issue/Jira status for import_issues." },
status: { type: "string", description: "Optional sprint status for create/update, Jira status (open, in_progress, done, all), or provider status for import_issues." },
showcasePinned: { type: "boolean", description: "Optional for create and update." },
agentPresetId: { type: "string", description: "Optional for create and update." },
planningAgentPresetId: { type: "string", description: "Optional for plan." },
autoStart: { type: "boolean", description: "Optional for plan and for import_issues when planAfterImport is true." },
replan: { type: "boolean", description: "Optional for plan." },
search: { type: "string", description: "Optional issue search query for import_issues." },
provider: { type: "string", enum: ["github", "gitlab", "jira"], description: "Optional issue provider for import_issues." },
provider: { type: "string", enum: ["github", "gitlab", "jira", "notion", "asana", "linear"], description: "Optional issue provider for import_issues." },
repository: { type: "string", description: "Optional repository owner/name or project path for import_issues." },
hostDomain: { type: "string", description: "Optional issue host domain for import_issues, such as github.com, gitlab.com, or a Jira site domain." },
workspaceId: { type: "string", description: "Optional provider workspace id for Notion, Asana, and Linear imports." },
providerProjectId: { type: "string", description: "Optional provider project id for Asana or Linear imports. Use this instead of Code UX projectId." },
externalProjectId: { type: "string", description: "Alias for providerProjectId on import_issues." },
asanaProjectId: { type: "string", description: "Alias for providerProjectId when importing Asana tasks." },
linearProjectId: { type: "string", description: "Alias for providerProjectId when importing Linear issues." },
teamId: { type: "string", description: "Optional Linear team id for import_issues." },
teamKey: { type: "string", description: "Optional Linear team key for import_issues." },
databaseId: { type: "string", description: "Optional Notion database id for import_issues." },
projectKey: { type: "string", description: "Optional Jira project key for import_issues." },
state: { type: "string", enum: ["open", "closed", "all"], description: "Optional GitHub/GitLab issue state for import_issues." },
state: { type: "string", description: "Optional GitHub/GitLab issue state (open, closed, all) or Linear workflow state for import_issues." },
labels: { type: "array", items: { type: "string" }, description: "Optional labels to filter or identify imported issues." },
assignee: { type: "string", description: "Optional GitHub/GitLab assignee filter for import_issues." },
assigneeText: { type: "string", description: "Optional Jira assignee text filter for import_issues, such as me, unassigned, or an account identifier." },
issueText: { type: "string", description: "Optional issue text or exact issue reference for import_issues." },
issueKeys: { type: "array", items: { type: "string" }, description: "Optional explicit Jira issue keys for import_issues." },
issueNumbers: { type: "array", items: { type: "number" }, description: "Optional explicit GitHub/GitLab issue numbers for import_issues." },
issueRefs: { type: "array", items: { type: "string" }, description: "Optional explicit issue references for import_issues, such as #123 or OPS-42." },
externalIds: { type: "array", items: { type: "string" }, description: "Optional explicit Notion page/database ids, Asana task gids, or Linear issue ids/identifiers for import_issues." },
includeConversation: { type: "boolean", description: "Optional import_issues flag controlling whether issue comments/conversation are included." },
attachToSprint: { type: "boolean", description: "Optional import_issues flag controlling whether matching issues should be attached to sprintId when provided." },
planAfterImport: { type: "boolean", description: "Optional import_issues flag requesting sprint planning after imported issues are attached." },
Expand Down
Loading