@geeks.ltd/geeks-amp-mcp 1.0.6 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -5
- package/dist/ampToolArgs.d.ts +32 -0
- package/dist/ampToolArgs.js +71 -0
- package/dist/ampToolArgs.test.d.ts +1 -0
- package/dist/ampToolArgs.test.js +58 -0
- package/dist/index.js +161 -21
- package/dist/tools.js +213 -9
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Local MCP server for Cursor and Claude that authenticates to your AMP backend vi
|
|
|
8
8
|
|
|
9
9
|
1. **First use** – When you call an AMP tool, the server opens your browser to AMP’s login. After you sign in, AMP redirects to `http://127.0.0.1:5005/callback`. The server exchanges the code for access and refresh tokens and stores them (e.g. in `~/.amp-mcp/credentials.json`).
|
|
10
10
|
2. **Later uses** – The server reuses the stored access token. When it expires, it uses the refresh token; if refresh fails, it runs the browser flow again.
|
|
11
|
-
3. **Tools** – `get_user_projects`, `get_projects`, `get_amp_item`, `get_active_workplans`, `get_workplan_items`, `get_amp_comments`, `get_amp_item_with_test_cases`, `create_amp`, `add_amp_update`, `submit_amp_progress_update`, `add_amp_test_case_references`, `submit_pen_test_review`, `audit_tdd_amp`, and `audit_pen_test_amp` are forwarded to AMP with `Authorization: Bearer <token>`. `get_auth_status` reports the local authentication state without calling AMP.
|
|
11
|
+
3. **Tools** – `get_user_projects`, `list_project_tags`, `create_project_tag`, `update_project_tag`, `delete_project_tag`, `get_amp_item_tags`, `add_amp_item_tags`, `remove_amp_item_tags`, `get_projects`, `get_amp_item`, `get_workplans`, `get_active_workplans`, `get_workplan_items`, `get_amp_comments`, `get_amp_item_with_test_cases`, `create_amp`, `add_amp_update`, `submit_amp_progress_update`, `add_amp_test_case_references`, `submit_pen_test_review`, `audit_tdd_amp`, and `audit_pen_test_amp` are forwarded to AMP with `Authorization: Bearer <token>`. `get_auth_status` reports the local authentication state without calling AMP.
|
|
12
12
|
|
|
13
13
|
## Prerequisites
|
|
14
14
|
|
|
@@ -66,15 +66,20 @@ In `.cursor/mcp.json` (project or global), use the **local server** via npx (no
|
|
|
66
66
|
## Tools
|
|
67
67
|
|
|
68
68
|
- **get_auth_status** – Returns `Authenticated: YES` or `Authenticated: NO` (no browser).
|
|
69
|
-
- **get_user_projects** – Non-archived projects the authenticated user belongs to: `{ projects: [{ id, key, name }] }`, ordered by key. Use this before `create_amp`.
|
|
69
|
+
- **get_user_projects** – Non-archived projects the authenticated user belongs to: `{ projects: [{ id, key, name }] }`, ordered by key. Use this before `create_amp` or `list_project_tags`.
|
|
70
|
+
- **list_project_tags** – List or search project tags (`project`, optional `search`, optional `includeArchived`). Returns tag id, name, description, visibility, and archived state.
|
|
71
|
+
- **create_project_tag** / **update_project_tag** / **delete_project_tag** – Manage project tags (project manager only). Delete is blocked when a tag is still on work items; archive instead.
|
|
72
|
+
- **get_amp_item_tags** – Read an item's current tags without changing it.
|
|
73
|
+
- **add_amp_item_tags** / **remove_amp_item_tags** – Add or remove specific tags while leaving other tags unchanged (project manager only).
|
|
70
74
|
- **get_projects** – Legacy global project search (optional `searchTerm`, `limit`); returns id + name only, not user-scoped. Do not use for create flows.
|
|
71
75
|
- **get_amp_item** – Rich details for an authorized AMP by `ampReference` (`12345` or `AMP-12345`): metadata, project, type, priority, status/progress/stage, completion, assignees, workplans, tags, URLs, linked AMPs, extension relationships (`extendedFrom`, `extensions`), pen-test review fields, and test case references. It does not return full comment history; use `get_amp_comments` for the conversation.
|
|
76
|
+
- **get_workplans** – All workplans in a project (active and inactive), including Backlog. Required: `project` (key or GUID). Returns name, dates, teams, and `isActive`. Use `get_workplan_items` with a workplan name or GUID to load that plan's AMPs.
|
|
72
77
|
- **get_active_workplans** – Active workplans for a project (there may be several). Required: `project` (key or GUID). Returns dates, teams, estimate/duration, completion %, and item counts. Use `get_workplan_items` with a workplan name or GUID to load that plan's AMPs.
|
|
73
|
-
- **get_workplan_items** – All items in a workplan, assigned to any user. Required: `project`. Optional: `workplan` (name or GUID from `get_active_workplans`; omit for the newest active plan), `assignee` (name, email, or user GUID), `progress` (`Not started`, `TDD`, `Developing`, `Testing`, `Done`, `Blocked`). Returns workplan metadata, applied filters, and items in workplan order.
|
|
78
|
+
- **get_workplan_items** – All items in a workplan, assigned to any user. Required: `project`. Optional: `workplan` (name or GUID from `get_workplans` / `get_active_workplans`; omit for the newest active plan), `assignee` (name, email, or user GUID), `progress` (`Not started`, `TDD`, `Developing`, `Testing`, `Done`, `Blocked`). Returns workplan metadata, applied filters, and items in workplan order.
|
|
74
79
|
- **get_amp_comments** – Authorized AMP comment history, newest first. Required: `ampReference`. Optional: `column` (`Team`, `Client`, `Director`, or `all`) and `limit` (1–500). With no column, AMP returns every column visible to the authenticated user's role; with no limit, it returns all visible comments. The response reports visible/returned counts and truncation, and includes decoded text, author, column, status/progress changes, assignees, and attachment URLs.
|
|
75
|
-
- **create_amp** – Create a new work item (status New). Required: `project` (key or GUID from `get_user_projects`), `subject`, `type`, `priority`. Optional: `description`, `url`, `note`, `visualSpecLink`, `linkedWorkItems`, `parentAmpReference
|
|
80
|
+
- **create_amp** – Create a new work item (status New). Required: `project` (key or GUID from `get_user_projects`), `subject`, `type`, `priority`. Optional: `description`, `url`, `note`, `visualSpecLink`, `linkedWorkItems`, `parentAmpReference`, `tags` (project manager only). Response includes `reference`, `projectId`, `projectKey`, `projectName`, `url`, etc.
|
|
76
81
|
- **get_amp_item_with_test_cases** – Existing TDD/pen-test-focused subset by `ampReference`. It requires authenticated access. Prefer `get_amp_item` plus `get_amp_comments` for general agent workflows.
|
|
77
|
-
- **add_amp_update** – Team-column update (mirrors Form_EnterComment team fields except assignees/attachments). Required: `ampReference` plus at least one of `message`, `teamPercentageDone` (0–100, step 10), `teamProgress` (Not started, TDD, Developing, Testing, Done, Blocked),
|
|
82
|
+
- **add_amp_update** – Team-column update (mirrors Form_EnterComment team fields except assignees/attachments). Required: `ampReference` plus at least one of `message`, `teamPercentageDone` (0–100, step 10), `teamProgress` (Not started, TDD, Developing, Testing, Done, Blocked), `stage` (Test, Local, UAT, Live, Pre-Live), or `tags`. Optional `tags` replaces the complete tag set (project manager only); omit `tags` to keep current tags, `[]` clears all. Use `add_amp_item_tags` / `remove_amp_item_tags` to change some tags without replacing the rest. Stage changes post a separate `"Done on: {stage}"` comment.
|
|
78
83
|
- **submit_amp_progress_update** – Team board: optional `teamPercentageDone` (0, 10, …, 100) and/or `message`; at least one required. Omits `message` when only updating % so AMP can default the comment to `"{n}% completed"`.
|
|
79
84
|
- **add_amp_test_case_references** – `ampReference`, required `testCaseReferences` (array of strings), optional `message` after refs; same as AMP “Update test cases” (`[#+REF#]` markers).
|
|
80
85
|
- **submit_pen_test_review** – Record a completed Cursor AI pen test review: required `ampReference` and `scope` (branch, commits, files, or PR reviewed); optional `findings` (one per line, or `"None"`), `falsePositives` (`"N/A"` if none), `knownRisks` (`"N/A"` if none), `summary`. Posts a team comment with `[#PENTEST:COMPLETE#]` and sets review metadata on the work item.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Copy tags onto a tool payload only when the caller set the field. Undefined must not clear tags. */
|
|
3
|
+
export declare function includeTags(args: Record<string, unknown>, tags: string[] | undefined): Record<string, unknown>;
|
|
4
|
+
/** Copy assignees onto a tool payload only when the caller set the field. Undefined must not clear assignees. */
|
|
5
|
+
export declare function includeAssignees(args: Record<string, unknown>, assignees: string[] | undefined): Record<string, unknown>;
|
|
6
|
+
export declare function hasAddAmpUpdatePayload(input: {
|
|
7
|
+
message?: string;
|
|
8
|
+
teamPercentageDone?: number;
|
|
9
|
+
teamProgress?: string;
|
|
10
|
+
stage?: string;
|
|
11
|
+
tags?: string[];
|
|
12
|
+
assignees?: string[];
|
|
13
|
+
}): boolean;
|
|
14
|
+
export declare const projectKeySchema: z.ZodString;
|
|
15
|
+
export declare const ampReferenceSchema: z.ZodString;
|
|
16
|
+
export declare const tagNameSchema: z.ZodString;
|
|
17
|
+
export declare const listProjectTagsSchema: {
|
|
18
|
+
project: z.ZodString;
|
|
19
|
+
search: z.ZodOptional<z.ZodString>;
|
|
20
|
+
includeArchived: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
+
};
|
|
22
|
+
export declare const itemTagChangeSchema: {
|
|
23
|
+
ampReference: z.ZodString;
|
|
24
|
+
tags: z.ZodArray<z.ZodString, "many">;
|
|
25
|
+
};
|
|
26
|
+
export declare const optionalTagsSchema: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
27
|
+
export declare const assigneeNameSchema: z.ZodString;
|
|
28
|
+
export declare const optionalAssigneesSchema: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
29
|
+
export declare const listAssignableUsersSchema: {
|
|
30
|
+
project: z.ZodString;
|
|
31
|
+
column: z.ZodOptional<z.ZodString>;
|
|
32
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Copy tags onto a tool payload only when the caller set the field. Undefined must not clear tags. */
|
|
3
|
+
export function includeTags(args, tags) {
|
|
4
|
+
if (tags !== undefined)
|
|
5
|
+
args.tags = tags;
|
|
6
|
+
return args;
|
|
7
|
+
}
|
|
8
|
+
/** Copy assignees onto a tool payload only when the caller set the field. Undefined must not clear assignees. */
|
|
9
|
+
export function includeAssignees(args, assignees) {
|
|
10
|
+
if (assignees !== undefined)
|
|
11
|
+
args.assignees = assignees;
|
|
12
|
+
return args;
|
|
13
|
+
}
|
|
14
|
+
export function hasAddAmpUpdatePayload(input) {
|
|
15
|
+
const hasMessage = input.message !== undefined && input.message.trim().length > 0;
|
|
16
|
+
return (hasMessage ||
|
|
17
|
+
input.teamPercentageDone !== undefined ||
|
|
18
|
+
input.teamProgress !== undefined ||
|
|
19
|
+
input.stage !== undefined ||
|
|
20
|
+
input.tags !== undefined ||
|
|
21
|
+
input.assignees !== undefined);
|
|
22
|
+
}
|
|
23
|
+
export const projectKeySchema = z
|
|
24
|
+
.string()
|
|
25
|
+
.min(1)
|
|
26
|
+
.describe("Project key (preferred) or GUID from get_user_projects");
|
|
27
|
+
export const ampReferenceSchema = z
|
|
28
|
+
.string()
|
|
29
|
+
.min(1)
|
|
30
|
+
.describe("AMP reference, e.g. '12345' or 'AMP-12345'");
|
|
31
|
+
export const tagNameSchema = z
|
|
32
|
+
.string()
|
|
33
|
+
.min(1)
|
|
34
|
+
.describe("Project tag GUID or name from list_project_tags");
|
|
35
|
+
export const listProjectTagsSchema = {
|
|
36
|
+
project: projectKeySchema,
|
|
37
|
+
search: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Optional text matched against tag name or description"),
|
|
41
|
+
includeArchived: z
|
|
42
|
+
.boolean()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("Include archived tags (default false)"),
|
|
45
|
+
};
|
|
46
|
+
export const itemTagChangeSchema = {
|
|
47
|
+
ampReference: ampReferenceSchema,
|
|
48
|
+
tags: z
|
|
49
|
+
.array(tagNameSchema)
|
|
50
|
+
.min(1)
|
|
51
|
+
.describe("One or more project tags. Unlisted tags on the item are left unchanged."),
|
|
52
|
+
};
|
|
53
|
+
export const optionalTagsSchema = z
|
|
54
|
+
.array(tagNameSchema)
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("Project tags (GUID or name from list_project_tags). Omit to leave tags unchanged.");
|
|
57
|
+
export const assigneeNameSchema = z
|
|
58
|
+
.string()
|
|
59
|
+
.min(1)
|
|
60
|
+
.describe("Team assignee name, email, or user GUID from list_assignable_users");
|
|
61
|
+
export const optionalAssigneesSchema = z
|
|
62
|
+
.array(assigneeNameSchema)
|
|
63
|
+
.optional()
|
|
64
|
+
.describe("Team assignees. Omit to leave assignees unchanged; [] unassigns.");
|
|
65
|
+
export const listAssignableUsersSchema = {
|
|
66
|
+
project: projectKeySchema,
|
|
67
|
+
column: z
|
|
68
|
+
.string()
|
|
69
|
+
.optional()
|
|
70
|
+
.describe("Team (default) or Director. Client column does not use this assignee list."),
|
|
71
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { hasAddAmpUpdatePayload, includeAssignees, includeTags, itemTagChangeSchema, listAssignableUsersSchema, listProjectTagsSchema, } from "./ampToolArgs.js";
|
|
5
|
+
describe("includeTags", () => {
|
|
6
|
+
it("omits tags when the caller did not set them", () => {
|
|
7
|
+
const args = includeTags({ project: "GTech", subject: "Fix" }, undefined);
|
|
8
|
+
assert.equal("tags" in args, false);
|
|
9
|
+
});
|
|
10
|
+
it("sends an empty list when the caller clears tags", () => {
|
|
11
|
+
const args = includeTags({ ampReference: "181526" }, []);
|
|
12
|
+
assert.deepEqual(args.tags, []);
|
|
13
|
+
});
|
|
14
|
+
it("sends the supplied tag names", () => {
|
|
15
|
+
const args = includeTags({}, ["Bug", "UI"]);
|
|
16
|
+
assert.deepEqual(args.tags, ["Bug", "UI"]);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe("includeAssignees", () => {
|
|
20
|
+
it("omits assignees when the caller did not set them", () => {
|
|
21
|
+
const args = includeAssignees({ ampReference: "181526" }, undefined);
|
|
22
|
+
assert.equal("assignees" in args, false);
|
|
23
|
+
});
|
|
24
|
+
it("sends an empty list when the caller unassigns everyone", () => {
|
|
25
|
+
const args = includeAssignees({ ampReference: "181526" }, []);
|
|
26
|
+
assert.deepEqual(args.assignees, []);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe("hasAddAmpUpdatePayload", () => {
|
|
30
|
+
it("accepts a tags-only replace and rejects a completely empty update", () => {
|
|
31
|
+
assert.equal(hasAddAmpUpdatePayload({ tags: ["Bug"] }), true);
|
|
32
|
+
assert.equal(hasAddAmpUpdatePayload({ tags: [] }), true);
|
|
33
|
+
assert.equal(hasAddAmpUpdatePayload({ assignees: ["jane@example.com"] }), true);
|
|
34
|
+
assert.equal(hasAddAmpUpdatePayload({ assignees: [] }), true);
|
|
35
|
+
assert.equal(hasAddAmpUpdatePayload({ message: " " }), false);
|
|
36
|
+
assert.equal(hasAddAmpUpdatePayload({}), false);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("tag tool schemas", () => {
|
|
40
|
+
it("requires a project for list and at least one tag to add or remove", () => {
|
|
41
|
+
const list = z.object(listProjectTagsSchema);
|
|
42
|
+
assert.equal(list.safeParse({}).success, false);
|
|
43
|
+
assert.equal(list.safeParse({ project: "GTech", search: "bug" }).success, true);
|
|
44
|
+
const change = z.object(itemTagChangeSchema);
|
|
45
|
+
assert.equal(change.safeParse({ ampReference: "AMP-181526", tags: ["Bug"] }).success, true);
|
|
46
|
+
assert.equal(change.safeParse({ ampReference: "181526", tags: [] }).success, false);
|
|
47
|
+
assert.equal(change.safeParse({ ampReference: "", tags: ["Bug"] }).success, false);
|
|
48
|
+
assert.equal(change.safeParse({ ampReference: "nope" }).success, false);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe("listAssignableUsersSchema", () => {
|
|
52
|
+
it("requires a project and accepts an optional column", () => {
|
|
53
|
+
const schema = z.object(listAssignableUsersSchema);
|
|
54
|
+
assert.equal(schema.safeParse({}).success, false);
|
|
55
|
+
assert.equal(schema.safeParse({ project: "GTech" }).success, true);
|
|
56
|
+
assert.equal(schema.safeParse({ project: "GTech", column: "Director" }).success, true);
|
|
57
|
+
});
|
|
58
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
+
import { hasAddAmpUpdatePayload, includeAssignees, includeTags, itemTagChangeSchema, listAssignableUsersSchema, listProjectTagsSchema, optionalAssigneesSchema, optionalTagsSchema, } from "./ampToolArgs.js";
|
|
9
10
|
import { ensureAccessToken, getAuthStatus } from "./auth.js";
|
|
10
11
|
import { callAmpTool } from "./tools.js";
|
|
11
12
|
const teamProgressValues = [
|
|
@@ -37,11 +38,18 @@ const createAmpSchema = z.object({
|
|
|
37
38
|
.string()
|
|
38
39
|
.optional()
|
|
39
40
|
.describe("Optional parent AMP reference, e.g. '12345' or 'AMP-12345'"),
|
|
41
|
+
tags: optionalTagsSchema,
|
|
42
|
+
assignees: optionalAssigneesSchema.describe("Optional team assignees. Posts a Team comment so the item shows as assigned."),
|
|
40
43
|
});
|
|
44
|
+
const teamProgressFieldDescription = "Team workflow stage. ONLY set when the user explicitly asked to move team progress — omit for comment-only updates. Advance one step: Not started → TDD → Developing → Testing → Done (never skip; from Developing use Testing, not Done).";
|
|
45
|
+
const addAmpUpdateToolDescription = 'Post a team-column update on an AMP item, matching the AMP UI team comment form. Default to message-only comments. Do NOT set teamProgress, teamPercentageDone, or stage unless the user explicitly asked to move the board — reporting finished work or posting an update is not the same as advancing progress. When teamProgress is requested, advance one step only along Not started → TDD → Developing → Testing → Done (never skip steps; from Developing go to Testing, not Done). Changing stage posts a separate "Done on: {stage}" comment.';
|
|
41
46
|
const addAmpUpdateSchema = z
|
|
42
47
|
.object({
|
|
43
48
|
ampReference: z.string().min(1).describe("e.g. '12345' or 'AMP-12345'"),
|
|
44
|
-
message: z
|
|
49
|
+
message: z
|
|
50
|
+
.string()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe("Team comment text. Safe default when the user only asked for a comment or progress note."),
|
|
45
53
|
teamPercentageDone: z
|
|
46
54
|
.number()
|
|
47
55
|
.int()
|
|
@@ -49,25 +57,23 @@ const addAmpUpdateSchema = z
|
|
|
49
57
|
.max(100)
|
|
50
58
|
.refine((n) => n % 10 === 0, "Must be a multiple of 10 (0, 10, …, 100)")
|
|
51
59
|
.optional()
|
|
52
|
-
.describe("Team % done (0–100, step 10)"),
|
|
60
|
+
.describe("Team board % done (0–100, step 10). ONLY set when the user explicitly asked to change % done — omit for comment-only updates."),
|
|
53
61
|
teamProgress: z
|
|
54
62
|
.enum(teamProgressValues)
|
|
55
63
|
.optional()
|
|
56
|
-
.describe(
|
|
64
|
+
.describe(teamProgressFieldDescription),
|
|
57
65
|
stage: z
|
|
58
66
|
.enum(stageValues)
|
|
59
67
|
.optional()
|
|
60
|
-
.describe('
|
|
68
|
+
.describe('Deployment stage. ONLY set when the user explicitly asked to record a stage change — omit for comment-only updates. Posts separate "Done on: {stage}" comment when changed.'),
|
|
69
|
+
tags: optionalTagsSchema.describe("Replace the complete tag set (project manager only). Omit to keep current tags; [] clears all. Use add_amp_item_tags or remove_amp_item_tags to change some tags without replacing the rest."),
|
|
70
|
+
assignees: optionalAssigneesSchema.describe("Replace team assignees. Omit to keep current assignees; [] unassigns. Defaults message to 'Assigning' if nothing else is posted."),
|
|
61
71
|
})
|
|
62
72
|
.superRefine((val, ctx) => {
|
|
63
|
-
|
|
64
|
-
val.teamPercentageDone !== undefined ||
|
|
65
|
-
val.teamProgress !== undefined ||
|
|
66
|
-
val.stage !== undefined;
|
|
67
|
-
if (!hasUpdate) {
|
|
73
|
+
if (!hasAddAmpUpdatePayload(val)) {
|
|
68
74
|
ctx.addIssue({
|
|
69
75
|
code: z.ZodIssueCode.custom,
|
|
70
|
-
message: "Provide at least one of message, teamPercentageDone, teamProgress, or
|
|
76
|
+
message: "Provide at least one of message, teamPercentageDone, teamProgress, stage, tags, or assignees.",
|
|
71
77
|
});
|
|
72
78
|
}
|
|
73
79
|
});
|
|
@@ -128,10 +134,88 @@ async function main() {
|
|
|
128
134
|
return callAmpTool("get_projects", args, token);
|
|
129
135
|
});
|
|
130
136
|
// get_user_projects – projects the authenticated user can use
|
|
131
|
-
server.tool("get_user_projects", "List non-archived projects the authenticated user belongs to (id, key, name), ordered by key. Use before create_amp to pick a valid project key or GUID.", {}, async () => {
|
|
137
|
+
server.tool("get_user_projects", "List non-archived projects the authenticated user belongs to (id, key, name), ordered by key. Use before create_amp or list_project_tags to pick a valid project key or GUID.", {}, async () => {
|
|
132
138
|
const token = await ensureAccessToken();
|
|
133
139
|
return callAmpTool("get_user_projects", {}, token);
|
|
134
140
|
});
|
|
141
|
+
server.tool("list_assignable_users", "List people who can be assigned on a project's Team (or Director) column. Use before create_amp or add_amp_update when setting assignees.", listAssignableUsersSchema, async (args) => {
|
|
142
|
+
const token = await ensureAccessToken();
|
|
143
|
+
const payload = { project: args.project };
|
|
144
|
+
if (args.column !== undefined && args.column.trim() !== "")
|
|
145
|
+
payload.column = args.column.trim();
|
|
146
|
+
return callAmpTool("list_assignable_users", payload, token);
|
|
147
|
+
});
|
|
148
|
+
server.tool("list_project_tags", "List or search tags defined on an AMP project (id, name, description, visibility, archived state). Any project member can list tags; creating or changing tags requires a project manager.", listProjectTagsSchema, async (args) => {
|
|
149
|
+
const token = await ensureAccessToken();
|
|
150
|
+
const payload = { project: args.project };
|
|
151
|
+
if (args.search !== undefined && args.search.trim() !== "")
|
|
152
|
+
payload.search = args.search.trim();
|
|
153
|
+
if (args.includeArchived !== undefined)
|
|
154
|
+
payload.includeArchived = args.includeArchived;
|
|
155
|
+
return callAmpTool("list_project_tags", payload, token);
|
|
156
|
+
});
|
|
157
|
+
server.tool("create_project_tag", "Create a new tag on an AMP project. Requires project manager. Returns tag id and name.", {
|
|
158
|
+
project: listProjectTagsSchema.project,
|
|
159
|
+
value: z.string().min(1).describe("Tag label (unique within the project)"),
|
|
160
|
+
description: z
|
|
161
|
+
.string()
|
|
162
|
+
.optional()
|
|
163
|
+
.describe("Optional tooltip description"),
|
|
164
|
+
isVisibleToClient: z
|
|
165
|
+
.boolean()
|
|
166
|
+
.optional()
|
|
167
|
+
.describe("Whether clients can see this tag (default false)"),
|
|
168
|
+
color: z.string().optional().describe("Optional CSS colour"),
|
|
169
|
+
}, async (args) => {
|
|
170
|
+
const token = await ensureAccessToken();
|
|
171
|
+
return callAmpTool("create_project_tag", args, token);
|
|
172
|
+
});
|
|
173
|
+
server.tool("update_project_tag", "Update a project tag's name, description, client visibility, colour, or archived state. Requires project manager. Identify the tag by GUID or name within the project.", {
|
|
174
|
+
project: listProjectTagsSchema.project,
|
|
175
|
+
tag: z
|
|
176
|
+
.string()
|
|
177
|
+
.min(1)
|
|
178
|
+
.describe("Tag GUID or name from list_project_tags"),
|
|
179
|
+
value: z.string().optional().describe("New tag label"),
|
|
180
|
+
description: z
|
|
181
|
+
.string()
|
|
182
|
+
.optional()
|
|
183
|
+
.describe("New description (empty string clears)"),
|
|
184
|
+
isVisibleToClient: z
|
|
185
|
+
.boolean()
|
|
186
|
+
.optional()
|
|
187
|
+
.describe("Whether clients can see this tag"),
|
|
188
|
+
isArchived: z
|
|
189
|
+
.boolean()
|
|
190
|
+
.optional()
|
|
191
|
+
.describe("Archive (true) or restore (false) the tag"),
|
|
192
|
+
color: z.string().optional().describe("CSS colour for the tag"),
|
|
193
|
+
}, async (args) => {
|
|
194
|
+
const token = await ensureAccessToken();
|
|
195
|
+
return callAmpTool("update_project_tag", args, token);
|
|
196
|
+
});
|
|
197
|
+
server.tool("delete_project_tag", "Delete a project tag that is not assigned to any work items. Requires project manager. Use update_project_tag with isArchived=true to retire tags still in use.", {
|
|
198
|
+
project: listProjectTagsSchema.project,
|
|
199
|
+
tag: z
|
|
200
|
+
.string()
|
|
201
|
+
.min(1)
|
|
202
|
+
.describe("Tag GUID or name from list_project_tags"),
|
|
203
|
+
}, async (args) => {
|
|
204
|
+
const token = await ensureAccessToken();
|
|
205
|
+
return callAmpTool("delete_project_tag", args, token);
|
|
206
|
+
});
|
|
207
|
+
server.tool("get_amp_item_tags", "Get the tags on an AMP item (id and name) that the authenticated user can see. Does not change the item.", { ampReference: itemTagChangeSchema.ampReference }, async ({ ampReference }) => {
|
|
208
|
+
const token = await ensureAccessToken();
|
|
209
|
+
return callAmpTool("get_amp_item_tags", { ampReference }, token);
|
|
210
|
+
});
|
|
211
|
+
server.tool("add_amp_item_tags", "Add existing project tags to an AMP item. Other tags and item fields stay unchanged. Already-assigned tags are left as-is. Requires project manager.", itemTagChangeSchema, async (args) => {
|
|
212
|
+
const token = await ensureAccessToken();
|
|
213
|
+
return callAmpTool("add_amp_item_tags", args, token);
|
|
214
|
+
});
|
|
215
|
+
server.tool("remove_amp_item_tags", "Remove selected project tags from an AMP item. Tags not listed, and other item fields, stay unchanged. Tags that are not assigned are left as-is. Requires project manager.", itemTagChangeSchema, async (args) => {
|
|
216
|
+
const token = await ensureAccessToken();
|
|
217
|
+
return callAmpTool("remove_amp_item_tags", args, token);
|
|
218
|
+
});
|
|
135
219
|
// get_amp_item_with_test_cases – ensure token, then call AMP
|
|
136
220
|
server.tool("get_amp_item_with_test_cases", "Get AMP (work item) details and all its test case references for a given AMP item. Use the reference number (e.g. 12345) or AMP-12345 format. Returns subject, note, status, progress (workflow stage), teamPercentageDone (team board % done, 0–100 in steps of 10), project, pen test review status (hasPenTestReview, penTestReviewCompleted, penTestReviewCompletedBy, penTestReviewCommentId), and a list of test case references (e.g. +AVFD) with the comment they appear in.", {
|
|
137
221
|
ampReference: z.string().describe("AMP item reference number, e.g. '12345' or 'AMP-12345'"),
|
|
@@ -149,6 +233,51 @@ async function main() {
|
|
|
149
233
|
const token = await ensureAccessToken();
|
|
150
234
|
return callAmpTool("get_amp_item", { ampReference }, token);
|
|
151
235
|
});
|
|
236
|
+
server.tool("get_my_amp_items", "List open AMP work items assigned to the authenticated user across their projects, in the same order as the AMP home 'My Assigned AMPs' list. Use when the user asks to list their AMPs or see what is assigned to them. Optional project filter and keyword search. Paginated.", {
|
|
237
|
+
project: z
|
|
238
|
+
.string()
|
|
239
|
+
.optional()
|
|
240
|
+
.describe("Optional project key (preferred) or GUID from get_user_projects. Omit for all assigned projects."),
|
|
241
|
+
keyword: z
|
|
242
|
+
.string()
|
|
243
|
+
.optional()
|
|
244
|
+
.describe("Optional search text or AMP reference (e.g. 12345 or #12345)"),
|
|
245
|
+
skip: z
|
|
246
|
+
.number()
|
|
247
|
+
.int()
|
|
248
|
+
.min(0)
|
|
249
|
+
.optional()
|
|
250
|
+
.describe("Rows to skip (default 0)"),
|
|
251
|
+
take: z
|
|
252
|
+
.number()
|
|
253
|
+
.int()
|
|
254
|
+
.min(1)
|
|
255
|
+
.max(200)
|
|
256
|
+
.optional()
|
|
257
|
+
.describe("Page size (default 50, max 200)"),
|
|
258
|
+
}, async (args) => {
|
|
259
|
+
const token = await ensureAccessToken();
|
|
260
|
+
const payload = {};
|
|
261
|
+
if (args.project !== undefined && args.project.trim() !== "")
|
|
262
|
+
payload.project = args.project.trim();
|
|
263
|
+
if (args.keyword !== undefined && args.keyword.trim() !== "")
|
|
264
|
+
payload.keyword = args.keyword.trim();
|
|
265
|
+
if (args.skip !== undefined)
|
|
266
|
+
payload.skip = args.skip;
|
|
267
|
+
if (args.take !== undefined)
|
|
268
|
+
payload.take = args.take;
|
|
269
|
+
return callAmpTool("get_my_amp_items", payload, token);
|
|
270
|
+
});
|
|
271
|
+
// get_workplans – list all workplans in a project (active and inactive)
|
|
272
|
+
server.tool("get_workplans", "List all workplans in a project (active and inactive) with name, dates, teams, and active flag. Use get_workplan_items with a workplan name or GUID to load that plan's AMPs. Prefer get_active_workplans when you only need current active plans. Use get_user_projects for a project key.", {
|
|
273
|
+
project: z
|
|
274
|
+
.string()
|
|
275
|
+
.min(1)
|
|
276
|
+
.describe("Project key (preferred) or GUID from get_user_projects"),
|
|
277
|
+
}, async ({ project }) => {
|
|
278
|
+
const token = await ensureAccessToken();
|
|
279
|
+
return callAmpTool("get_workplans", { project }, token);
|
|
280
|
+
});
|
|
152
281
|
// get_active_workplans – list a project's active workplans (there may be several)
|
|
153
282
|
server.tool("get_active_workplans", "List a project's active workplans (there may be more than one) with dates, teams, estimates, completion, and item counts. Use get_workplan_items with a workplan name or GUID to load that plan's AMPs. Use get_user_projects for a project key.", {
|
|
154
283
|
project: z
|
|
@@ -160,7 +289,7 @@ async function main() {
|
|
|
160
289
|
return callAmpTool("get_active_workplans", { project }, token);
|
|
161
290
|
});
|
|
162
291
|
// get_workplan_items – all items in the project's active workplan (optional assignee/progress filters)
|
|
163
|
-
server.tool("get_workplan_items", "List all AMP items in a workplan, assigned to any user, in workplan order. Optional filters: assignee (name, email, or GUID) and progress (Not started, TDD, Developing, Testing, Done, Blocked). Pass workplan name or GUID from
|
|
292
|
+
server.tool("get_workplan_items", "List all AMP items in a workplan, assigned to any user, in workplan order. Optional filters: assignee (name, email, or GUID) and progress (Not started, TDD, Developing, Testing, Done, Blocked). Pass workplan name or GUID from get_workplans or get_active_workplans; omit workplan to use the newest active one. Use get_user_projects for a project key.", {
|
|
164
293
|
project: z
|
|
165
294
|
.string()
|
|
166
295
|
.min(1)
|
|
@@ -215,7 +344,7 @@ async function main() {
|
|
|
215
344
|
return callAmpTool("get_amp_comments", args, token);
|
|
216
345
|
});
|
|
217
346
|
// create_amp – new work item (status New)
|
|
218
|
-
server.tool("create_amp", "Create a new AMP work item with status New. Required project is a project key (preferred) or GUID from get_user_projects. User must belong to the project. Extension items add Team + Client column comments automatically.", {
|
|
347
|
+
server.tool("create_amp", "Create a new AMP work item with status New. Required project is a project key (preferred) or GUID from get_user_projects. User must belong to the project. Optional tags (project manager only). Optional assignees assigns the item to those team members (use list_assignable_users). Extension items add Team + Client column comments automatically.", {
|
|
219
348
|
project: z
|
|
220
349
|
.string()
|
|
221
350
|
.min(1)
|
|
@@ -238,6 +367,7 @@ async function main() {
|
|
|
238
367
|
.string()
|
|
239
368
|
.optional()
|
|
240
369
|
.describe("Optional parent AMP reference, e.g. '12345' or 'AMP-12345'"),
|
|
370
|
+
assignees: optionalAssigneesSchema.describe("Optional team assignees. Posts a Team comment so the item shows as assigned."),
|
|
241
371
|
}, async (raw) => {
|
|
242
372
|
const parsed = createAmpSchema.parse(raw);
|
|
243
373
|
const token = await ensureAccessToken();
|
|
@@ -259,31 +389,41 @@ async function main() {
|
|
|
259
389
|
args.linkedWorkItems = parsed.linkedWorkItems;
|
|
260
390
|
if (parsed.parentAmpReference !== undefined)
|
|
261
391
|
args.parentAmpReference = parsed.parentAmpReference;
|
|
392
|
+
if (parsed.tags !== undefined)
|
|
393
|
+
args.tags = parsed.tags;
|
|
394
|
+
if (parsed.assignees !== undefined)
|
|
395
|
+
args.assignees = parsed.assignees;
|
|
262
396
|
return callAmpTool("create_amp", args, token);
|
|
263
397
|
});
|
|
264
398
|
// add_amp_update – team-column update (Form_EnterComment team fields)
|
|
265
|
-
server.tool("add_amp_update",
|
|
399
|
+
server.tool("add_amp_update", addAmpUpdateToolDescription, {
|
|
266
400
|
ampReference: z.string().min(1).describe("e.g. '12345' or 'AMP-12345'"),
|
|
267
|
-
message: z
|
|
401
|
+
message: z
|
|
402
|
+
.string()
|
|
403
|
+
.optional()
|
|
404
|
+
.describe("Team comment text. Safe default when the user only asked for a comment or progress note."),
|
|
268
405
|
teamPercentageDone: z
|
|
269
406
|
.number()
|
|
270
407
|
.int()
|
|
271
408
|
.min(0)
|
|
272
409
|
.max(100)
|
|
273
410
|
.optional()
|
|
274
|
-
.describe("Team % done (0–100, step 10)"),
|
|
411
|
+
.describe("Team board % done (0–100, step 10). ONLY set when the user explicitly asked to change % done — omit for comment-only updates."),
|
|
275
412
|
teamProgress: z
|
|
276
413
|
.enum(teamProgressValues)
|
|
277
414
|
.optional()
|
|
278
|
-
.describe(
|
|
415
|
+
.describe(teamProgressFieldDescription),
|
|
279
416
|
stage: z
|
|
280
417
|
.enum(stageValues)
|
|
281
418
|
.optional()
|
|
282
|
-
.describe('
|
|
419
|
+
.describe('Deployment stage. ONLY set when the user explicitly asked to record a stage change — omit for comment-only updates. Posts separate "Done on: {stage}" comment when changed.'),
|
|
420
|
+
tags: optionalTagsSchema.describe("Replace the complete tag set (project manager only). Omit to keep current tags; [] clears all."),
|
|
421
|
+
assignees: optionalAssigneesSchema.describe("Replace team assignees. Omit to keep current assignees; [] unassigns. Defaults message to 'Assigning' if nothing else is posted."),
|
|
283
422
|
}, async (raw) => {
|
|
284
423
|
const parsed = addAmpUpdateSchema.parse(raw);
|
|
285
424
|
const token = await ensureAccessToken();
|
|
286
|
-
|
|
425
|
+
let args = includeTags({ ampReference: parsed.ampReference }, parsed.tags);
|
|
426
|
+
args = includeAssignees(args, parsed.assignees);
|
|
287
427
|
if (parsed.message !== undefined && parsed.message.trim() !== "")
|
|
288
428
|
args.message = parsed.message.trim();
|
|
289
429
|
if (parsed.teamPercentageDone !== undefined)
|
|
@@ -295,7 +435,7 @@ async function main() {
|
|
|
295
435
|
return callAmpTool("add_amp_update", args, token);
|
|
296
436
|
});
|
|
297
437
|
// submit_amp_progress_update – team board % done and/or team comment (AMP MCPServer parity)
|
|
298
|
-
server.tool("submit_amp_progress_update", "Update the AMP team board
|
|
438
|
+
server.tool("submit_amp_progress_update", "Update the AMP team board % done (0, 10, …, 100) and/or append a team-column comment. Does NOT change teamProgress (workflow stage). Do NOT set teamPercentageDone unless the user explicitly asked — omit for comment-only updates. At least one of teamPercentageDone or a non-empty message is required.", {
|
|
299
439
|
ampReference: z.string().min(1).describe("e.g. '12345' or 'AMP-12345'"),
|
|
300
440
|
teamPercentageDone: z
|
|
301
441
|
.number()
|
|
@@ -303,7 +443,7 @@ async function main() {
|
|
|
303
443
|
.min(0)
|
|
304
444
|
.max(100)
|
|
305
445
|
.optional()
|
|
306
|
-
.describe("Team % done (multiple of 10)
|
|
446
|
+
.describe("Team board % done (multiple of 10). ONLY set when the user explicitly asked — omit for comment-only updates."),
|
|
307
447
|
message: z.string().optional().describe("Team comment text"),
|
|
308
448
|
}, async (raw) => {
|
|
309
449
|
const parsed = submitAmpProgressUpdateSchema.parse(raw);
|
package/dist/tools.js
CHANGED
|
@@ -49,6 +49,45 @@ export const TOOL_DEFINITIONS = [
|
|
|
49
49
|
required: ["ampReference"],
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
|
+
{
|
|
53
|
+
name: "get_my_amp_items",
|
|
54
|
+
description: "List open AMP work items assigned to the authenticated user across their projects, in the same order as the AMP home 'My Assigned AMPs' list. Use when the user asks to list their AMPs or see what is assigned to them. Optional project filter and keyword search. Paginated.",
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: "object",
|
|
57
|
+
properties: {
|
|
58
|
+
project: {
|
|
59
|
+
type: "string",
|
|
60
|
+
description: "Optional project key (preferred) or GUID from get_user_projects. Omit for all assigned projects.",
|
|
61
|
+
},
|
|
62
|
+
keyword: {
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "Optional search text or AMP reference (e.g. 12345 or #12345)",
|
|
65
|
+
},
|
|
66
|
+
skip: {
|
|
67
|
+
type: "number",
|
|
68
|
+
description: "Rows to skip (default 0)",
|
|
69
|
+
},
|
|
70
|
+
take: {
|
|
71
|
+
type: "number",
|
|
72
|
+
description: "Page size (default 50, max 200)",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "get_workplans",
|
|
79
|
+
description: "List all workplans in a project (active and inactive) with name, dates, teams, and active flag. Use get_workplan_items with a workplan name or GUID to load that plan's AMPs. Prefer get_active_workplans when you only need current active plans. Use get_user_projects for a project key.",
|
|
80
|
+
inputSchema: {
|
|
81
|
+
type: "object",
|
|
82
|
+
properties: {
|
|
83
|
+
project: {
|
|
84
|
+
type: "string",
|
|
85
|
+
description: "Project key (preferred) or GUID from get_user_projects",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
required: ["project"],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
52
91
|
{
|
|
53
92
|
name: "get_active_workplans",
|
|
54
93
|
description: "List a project's active workplans (there may be more than one) with dates, teams, estimates, completion, and item counts. Use get_workplan_items with a workplan name or GUID to load that plan's AMPs. Use get_user_projects for a project key.",
|
|
@@ -65,7 +104,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
65
104
|
},
|
|
66
105
|
{
|
|
67
106
|
name: "get_workplan_items",
|
|
68
|
-
description: "List all AMP items in a workplan, assigned to any user, in workplan order. Optional filters: assignee (name, email, or GUID) and progress (Not started, TDD, Developing, Testing, Done, Blocked). Pass workplan name or GUID from
|
|
107
|
+
description: "List all AMP items in a workplan, assigned to any user, in workplan order. Optional filters: assignee (name, email, or GUID) and progress (Not started, TDD, Developing, Testing, Done, Blocked). Pass workplan name or GUID from get_workplans or get_active_workplans; omit workplan to use the newest active one. Use get_user_projects for a project key.",
|
|
69
108
|
inputSchema: {
|
|
70
109
|
type: "object",
|
|
71
110
|
properties: {
|
|
@@ -113,15 +152,160 @@ export const TOOL_DEFINITIONS = [
|
|
|
113
152
|
},
|
|
114
153
|
{
|
|
115
154
|
name: "get_user_projects",
|
|
116
|
-
description: "List non-archived projects the authenticated user belongs to (id, key, name), ordered by key. Use before create_amp to pick a valid project key or GUID.",
|
|
155
|
+
description: "List non-archived projects the authenticated user belongs to (id, key, name), ordered by key. Use before create_amp or list_project_tags to pick a valid project key or GUID.",
|
|
117
156
|
inputSchema: {
|
|
118
157
|
type: "object",
|
|
119
158
|
properties: {},
|
|
120
159
|
},
|
|
121
160
|
},
|
|
161
|
+
{
|
|
162
|
+
name: "list_assignable_users",
|
|
163
|
+
description: "List people who can be assigned on a project's Team (or Director) column. Use before create_amp or add_amp_update when setting assignees.",
|
|
164
|
+
inputSchema: {
|
|
165
|
+
type: "object",
|
|
166
|
+
properties: {
|
|
167
|
+
project: {
|
|
168
|
+
type: "string",
|
|
169
|
+
description: "Project key (preferred) or GUID from get_user_projects",
|
|
170
|
+
},
|
|
171
|
+
column: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "Team (default) or Director. Client column does not use this assignee list.",
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
required: ["project"],
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "list_project_tags",
|
|
181
|
+
description: "List or search tags defined on an AMP project (id, name, description, visibility, archived state). Any project member can list tags; creating or changing tags requires a project manager.",
|
|
182
|
+
inputSchema: {
|
|
183
|
+
type: "object",
|
|
184
|
+
properties: {
|
|
185
|
+
project: {
|
|
186
|
+
type: "string",
|
|
187
|
+
description: "Project key (preferred) or GUID from get_user_projects",
|
|
188
|
+
},
|
|
189
|
+
search: {
|
|
190
|
+
type: "string",
|
|
191
|
+
description: "Optional text matched against tag name or description",
|
|
192
|
+
},
|
|
193
|
+
includeArchived: {
|
|
194
|
+
type: "boolean",
|
|
195
|
+
description: "Include archived tags (default false)",
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
required: ["project"],
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: "create_project_tag",
|
|
203
|
+
description: "Create a new tag on an AMP project. Requires project manager. Returns tag id and name.",
|
|
204
|
+
inputSchema: {
|
|
205
|
+
type: "object",
|
|
206
|
+
properties: {
|
|
207
|
+
project: { type: "string", description: "Project key (preferred) or GUID" },
|
|
208
|
+
value: { type: "string", description: "Tag label (unique within the project)" },
|
|
209
|
+
description: { type: "string", description: "Optional tooltip description" },
|
|
210
|
+
isVisibleToClient: {
|
|
211
|
+
type: "boolean",
|
|
212
|
+
description: "Whether clients can see this tag (default false)",
|
|
213
|
+
},
|
|
214
|
+
color: { type: "string", description: "Optional CSS colour" },
|
|
215
|
+
},
|
|
216
|
+
required: ["project", "value"],
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: "update_project_tag",
|
|
221
|
+
description: "Update a project tag (name, description, client visibility, colour, archived). Requires project manager. Tag is GUID or name within the project.",
|
|
222
|
+
inputSchema: {
|
|
223
|
+
type: "object",
|
|
224
|
+
properties: {
|
|
225
|
+
project: { type: "string", description: "Project key (preferred) or GUID" },
|
|
226
|
+
tag: { type: "string", description: "Tag GUID or name from list_project_tags" },
|
|
227
|
+
value: { type: "string", description: "New tag label" },
|
|
228
|
+
description: { type: "string", description: "New description (empty string clears)" },
|
|
229
|
+
isVisibleToClient: {
|
|
230
|
+
type: "boolean",
|
|
231
|
+
description: "Whether clients can see this tag",
|
|
232
|
+
},
|
|
233
|
+
isArchived: {
|
|
234
|
+
type: "boolean",
|
|
235
|
+
description: "Archive (true) or restore (false) the tag",
|
|
236
|
+
},
|
|
237
|
+
color: { type: "string", description: "CSS colour for the tag" },
|
|
238
|
+
},
|
|
239
|
+
required: ["project", "tag"],
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: "delete_project_tag",
|
|
244
|
+
description: "Delete a project tag not assigned to any work items. Requires project manager.",
|
|
245
|
+
inputSchema: {
|
|
246
|
+
type: "object",
|
|
247
|
+
properties: {
|
|
248
|
+
project: { type: "string", description: "Project key (preferred) or GUID" },
|
|
249
|
+
tag: { type: "string", description: "Tag GUID or name from list_project_tags" },
|
|
250
|
+
},
|
|
251
|
+
required: ["project", "tag"],
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: "get_amp_item_tags",
|
|
256
|
+
description: "Get the tags on an AMP item (id and name) that the authenticated user can see. Does not change the item.",
|
|
257
|
+
inputSchema: {
|
|
258
|
+
type: "object",
|
|
259
|
+
properties: {
|
|
260
|
+
ampReference: {
|
|
261
|
+
type: "string",
|
|
262
|
+
description: "AMP reference, e.g. '12345' or 'AMP-12345'",
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
required: ["ampReference"],
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: "add_amp_item_tags",
|
|
270
|
+
description: "Add existing project tags to an AMP item without changing other tags. Requires project manager.",
|
|
271
|
+
inputSchema: {
|
|
272
|
+
type: "object",
|
|
273
|
+
properties: {
|
|
274
|
+
ampReference: {
|
|
275
|
+
type: "string",
|
|
276
|
+
description: "AMP reference, e.g. '12345' or 'AMP-12345'",
|
|
277
|
+
},
|
|
278
|
+
tags: {
|
|
279
|
+
type: "array",
|
|
280
|
+
items: { type: "string" },
|
|
281
|
+
description: "One or more project tags to add (GUID or name)",
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
required: ["ampReference", "tags"],
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: "remove_amp_item_tags",
|
|
289
|
+
description: "Remove selected project tags from an AMP item without changing other tags. Requires project manager.",
|
|
290
|
+
inputSchema: {
|
|
291
|
+
type: "object",
|
|
292
|
+
properties: {
|
|
293
|
+
ampReference: {
|
|
294
|
+
type: "string",
|
|
295
|
+
description: "AMP reference, e.g. '12345' or 'AMP-12345'",
|
|
296
|
+
},
|
|
297
|
+
tags: {
|
|
298
|
+
type: "array",
|
|
299
|
+
items: { type: "string" },
|
|
300
|
+
description: "One or more project tags to remove (GUID or name)",
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
required: ["ampReference", "tags"],
|
|
304
|
+
},
|
|
305
|
+
},
|
|
122
306
|
{
|
|
123
307
|
name: "create_amp",
|
|
124
|
-
description: "Create a new AMP work item with status New. Required project is a project key (preferred) or GUID from get_user_projects. User must belong to the project. Extension items add Team + Client column comments automatically.",
|
|
308
|
+
description: "Create a new AMP work item with status New. Required project is a project key (preferred) or GUID from get_user_projects. User must belong to the project. Optional assignees assigns the item to those team members (use list_assignable_users). Extension items add Team + Client column comments automatically.",
|
|
125
309
|
inputSchema: {
|
|
126
310
|
type: "object",
|
|
127
311
|
properties: {
|
|
@@ -166,13 +350,23 @@ export const TOOL_DEFINITIONS = [
|
|
|
166
350
|
type: "string",
|
|
167
351
|
description: "Optional parent AMP reference, e.g. '12345' or 'AMP-12345'",
|
|
168
352
|
},
|
|
353
|
+
tags: {
|
|
354
|
+
type: "array",
|
|
355
|
+
items: { type: "string" },
|
|
356
|
+
description: "Optional project tags (GUID or name from list_project_tags). Project manager only. Omit for no tags.",
|
|
357
|
+
},
|
|
358
|
+
assignees: {
|
|
359
|
+
type: "array",
|
|
360
|
+
items: { type: "string" },
|
|
361
|
+
description: "Optional team assignees (name, email, or user GUID from list_assignable_users). Posts a Team comment so the item shows as assigned.",
|
|
362
|
+
},
|
|
169
363
|
},
|
|
170
364
|
required: ["project", "subject", "type", "priority"],
|
|
171
365
|
},
|
|
172
366
|
},
|
|
173
367
|
{
|
|
174
368
|
name: "add_amp_update",
|
|
175
|
-
description: "Post a team-column update on an AMP item
|
|
369
|
+
description: "Post a team-column update on an AMP item, matching the AMP UI team comment form. Default to message-only comments. Do NOT set teamProgress, teamPercentageDone, or stage unless the user explicitly asked to move the board — reporting finished work or posting an update is not the same as advancing progress. When teamProgress is requested, advance one step only along Not started → TDD → Developing → Testing → Done (never skip steps; from Developing go to Testing, not Done).",
|
|
176
370
|
inputSchema: {
|
|
177
371
|
type: "object",
|
|
178
372
|
properties: {
|
|
@@ -182,19 +376,29 @@ export const TOOL_DEFINITIONS = [
|
|
|
182
376
|
},
|
|
183
377
|
message: {
|
|
184
378
|
type: "string",
|
|
185
|
-
description: "Team comment text",
|
|
379
|
+
description: "Team comment text. Safe default when the user only asked for a comment or progress note.",
|
|
186
380
|
},
|
|
187
381
|
teamPercentageDone: {
|
|
188
382
|
type: "number",
|
|
189
|
-
description: "Team % done; integer 0–100, multiple of 10",
|
|
383
|
+
description: "Team board % done; integer 0–100, multiple of 10. ONLY set when the user explicitly asked to change % done — omit for comment-only updates.",
|
|
190
384
|
},
|
|
191
385
|
teamProgress: {
|
|
192
386
|
type: "string",
|
|
193
|
-
description: "Team progress: Not started
|
|
387
|
+
description: "Team workflow stage. ONLY set when the user explicitly asked to move team progress — omit for comment-only updates. Advance one step: Not started → TDD → Developing → Testing → Done (never skip; from Developing use Testing, not Done).",
|
|
194
388
|
},
|
|
195
389
|
stage: {
|
|
196
390
|
type: "string",
|
|
197
|
-
description: "
|
|
391
|
+
description: "Deployment stage. ONLY set when the user explicitly asked to record a stage change — omit for comment-only updates.",
|
|
392
|
+
},
|
|
393
|
+
tags: {
|
|
394
|
+
type: "array",
|
|
395
|
+
items: { type: "string" },
|
|
396
|
+
description: "Replace all tags on the item. Project manager only. Omit to keep current tags; [] clears all.",
|
|
397
|
+
},
|
|
398
|
+
assignees: {
|
|
399
|
+
type: "array",
|
|
400
|
+
items: { type: "string" },
|
|
401
|
+
description: "Replace team assignees. Omit to keep current assignees; [] unassigns. Defaults message to 'Assigning' if nothing else is posted.",
|
|
198
402
|
},
|
|
199
403
|
},
|
|
200
404
|
required: ["ampReference"],
|
|
@@ -202,7 +406,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
202
406
|
},
|
|
203
407
|
{
|
|
204
408
|
name: "submit_amp_progress_update",
|
|
205
|
-
description: "
|
|
409
|
+
description: "Update the AMP team board % done (0–100, multiple of 10) and/or append a team-column comment. Does NOT change teamProgress (workflow stage). Do NOT set teamPercentageDone unless the user explicitly asked — omit for comment-only updates. At least one of teamPercentageDone or non-empty message required.",
|
|
206
410
|
inputSchema: {
|
|
207
411
|
type: "object",
|
|
208
412
|
properties: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geeks.ltd/geeks-amp-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Local MCP server for AMP (OAuth 2.0 PKCE, token storage, proxy to AMP MCPServer.ashx)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsc",
|
|
20
|
+
"test": "node --import tsx --test src/**/*.test.ts",
|
|
20
21
|
"start": "node dist/index.js",
|
|
21
22
|
"dev": "node --import tsx src/index.ts"
|
|
22
23
|
},
|