@taiga-ai/mcp-server 0.37.0-rc.956 → 0.37.0-rc.984
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/dist/index.js +131 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23883,6 +23883,10 @@ var TaigaClient = class {
|
|
|
23883
23883
|
async listBuildRunSteps(id) {
|
|
23884
23884
|
return this.request("GET", `/builds/${seg(id)}/steps`);
|
|
23885
23885
|
}
|
|
23886
|
+
/** The public hosts the run reached through the egress gateway (PRO-4268). */
|
|
23887
|
+
async listBuildRunEgressHosts(id) {
|
|
23888
|
+
return this.request("GET", `/builds/${seg(id)}/hosts`);
|
|
23889
|
+
}
|
|
23886
23890
|
async getMaintenanceSummary(productId) {
|
|
23887
23891
|
return this.request("GET", `/products/${seg(productId)}/maintenance/summary`);
|
|
23888
23892
|
}
|
|
@@ -23957,6 +23961,10 @@ var TaigaClient = class {
|
|
|
23957
23961
|
async shipNotices(productId) {
|
|
23958
23962
|
return this.request("POST", `/products/${seg(productId)}/maintenance/notices`, {});
|
|
23959
23963
|
}
|
|
23964
|
+
/** Sweep one of a product's repositories (PRO-4276): its primary when none is named. */
|
|
23965
|
+
async startSweep(productId, productRepositoryId) {
|
|
23966
|
+
return this.request("POST", `/products/${seg(productId)}/maintenance/sweeps`, productRepositoryId ? { productRepositoryId } : {});
|
|
23967
|
+
}
|
|
23960
23968
|
async remediateFinding(productId, findingId) {
|
|
23961
23969
|
return this.request("POST", `/products/${seg(productId)}/maintenance/findings/${seg(findingId)}/remediate`, {});
|
|
23962
23970
|
}
|
|
@@ -26210,6 +26218,46 @@ const ENVIRONMENT_TYPES = [
|
|
|
26210
26218
|
"custom"
|
|
26211
26219
|
];
|
|
26212
26220
|
//#endregion
|
|
26221
|
+
//#region ../../packages/types/dist/monitoring-rollups.js
|
|
26222
|
+
/**
|
|
26223
|
+
* Core Web Vitals weighted heaviest (LCP/INP/CLS are Google's "Core" trio);
|
|
26224
|
+
* FCP/TTFB are supporting signals. Thresholds are the published web.dev values.
|
|
26225
|
+
*/
|
|
26226
|
+
const METRICS = {
|
|
26227
|
+
LCP: {
|
|
26228
|
+
good: 2500,
|
|
26229
|
+
ni: 4e3,
|
|
26230
|
+
unit: "ms",
|
|
26231
|
+
weight: 30
|
|
26232
|
+
},
|
|
26233
|
+
INP: {
|
|
26234
|
+
good: 200,
|
|
26235
|
+
ni: 500,
|
|
26236
|
+
unit: "ms",
|
|
26237
|
+
weight: 30
|
|
26238
|
+
},
|
|
26239
|
+
CLS: {
|
|
26240
|
+
good: .1,
|
|
26241
|
+
ni: .25,
|
|
26242
|
+
unit: "score",
|
|
26243
|
+
weight: 25
|
|
26244
|
+
},
|
|
26245
|
+
FCP: {
|
|
26246
|
+
good: 1800,
|
|
26247
|
+
ni: 3e3,
|
|
26248
|
+
unit: "ms",
|
|
26249
|
+
weight: 10
|
|
26250
|
+
},
|
|
26251
|
+
TTFB: {
|
|
26252
|
+
good: 800,
|
|
26253
|
+
ni: 1800,
|
|
26254
|
+
unit: "ms",
|
|
26255
|
+
weight: 5
|
|
26256
|
+
}
|
|
26257
|
+
};
|
|
26258
|
+
Object.keys(METRICS);
|
|
26259
|
+
Object.fromEntries(Object.entries(METRICS).map(([name, spec]) => [name, spec.weight]));
|
|
26260
|
+
//#endregion
|
|
26213
26261
|
//#region ../../packages/types/dist/api-keys.js
|
|
26214
26262
|
/**
|
|
26215
26263
|
* API key scopes control what operations a key can perform.
|
|
@@ -27218,16 +27266,18 @@ const EXCEL_MAX_ROW = 1048576;
|
|
|
27218
27266
|
* Where an engineer build's sandbox may connect to (PRO-2793, part of
|
|
27219
27267
|
* PRO-1980).
|
|
27220
27268
|
*
|
|
27221
|
-
* The
|
|
27222
|
-
*
|
|
27223
|
-
*
|
|
27224
|
-
*
|
|
27269
|
+
* The egress gateway is the sandbox's only way out for what the other
|
|
27270
|
+
* gateways do not carry (packages, images, toolchains, scanners). Reads are
|
|
27271
|
+
* open and writes are controlled (PRO-4266): every run is held to an upload
|
|
27272
|
+
* budget, the gateway refuses private and metadata addresses, and it never
|
|
27273
|
+
* hands the sandbox a credential, whichever access a product has.
|
|
27225
27274
|
*
|
|
27226
|
-
* - `
|
|
27227
|
-
*
|
|
27228
|
-
* - `
|
|
27229
|
-
*
|
|
27230
|
-
*
|
|
27275
|
+
* - `unrestricted` (the default, also what `null` means): any public host.
|
|
27276
|
+
* A list of hosts nobody can keep complete broke builds one host at a time.
|
|
27277
|
+
* - `allowlist`: only the gateway's standard list (the public package
|
|
27278
|
+
* registries, toolchain downloads, container registries, GitHub for public
|
|
27279
|
+
* dependencies, the tenant's own registries) plus the product's own
|
|
27280
|
+
* `networkHosts`. For a product that wants to name where its builds go.
|
|
27231
27281
|
*
|
|
27232
27282
|
* A host is one exact name (`api.example.com`). There are no wildcards: a
|
|
27233
27283
|
* wildcard over a multi-label public suffix (`*.co.uk`) or a provider's
|
|
@@ -27965,7 +28015,7 @@ const TOOLSET_PURPOSE = {
|
|
|
27965
28015
|
core: "where products, initiatives, runs, policies and findings stand",
|
|
27966
28016
|
operate: "moving work: queue, plans, runs, fixes, Action Required",
|
|
27967
28017
|
setup: "creating and configuring factories, products, repositories, environments and autonomy",
|
|
27968
|
-
observe: "deployments, monitoring, delivery metrics and the
|
|
28018
|
+
observe: "deployments, monitoring, delivery metrics, the package inventory and the sweeps that read it",
|
|
27969
28019
|
documents: "writing documents and knowledge, and regenerating product documents"
|
|
27970
28020
|
};
|
|
27971
28021
|
/** Every tool's toolset. A tool missing here fails at registration, so none can be added without a home. */
|
|
@@ -28032,6 +28082,7 @@ const TOOLSET_OF = {
|
|
|
28032
28082
|
taiga_get_monitoring: "observe",
|
|
28033
28083
|
taiga_get_delivery_metrics: "observe",
|
|
28034
28084
|
taiga_list_packages: "observe",
|
|
28085
|
+
taiga_start_sweep: "observe",
|
|
28035
28086
|
taiga_list_licenses: "observe",
|
|
28036
28087
|
taiga_change_license: "setup",
|
|
28037
28088
|
taiga_get_sbom: "observe",
|
|
@@ -34801,6 +34852,21 @@ const SWEEP_FIELDS = [
|
|
|
34801
34852
|
"createdAt",
|
|
34802
34853
|
"completedAt"
|
|
34803
34854
|
];
|
|
34855
|
+
/** Advisories a sweep's summary names, at most. */
|
|
34856
|
+
const ADVISORIES_SHOWN = 10;
|
|
34857
|
+
/**
|
|
34858
|
+
* The advisories whose arrival in OSV's feed started a sweep (PRO-116), only
|
|
34859
|
+
* where some did: a sweep a push, the clock or a person started says nothing.
|
|
34860
|
+
*/
|
|
34861
|
+
function startedByAdvisories(sweep) {
|
|
34862
|
+
const raw = sweep.advisories;
|
|
34863
|
+
const advisories = Array.isArray(raw) ? raw.filter((a) => typeof a === "string") : [];
|
|
34864
|
+
if (advisories.length === 0) return {};
|
|
34865
|
+
return advisories.length > ADVISORIES_SHOWN ? {
|
|
34866
|
+
advisories: advisories.slice(0, ADVISORIES_SHOWN),
|
|
34867
|
+
advisoriesCount: advisories.length
|
|
34868
|
+
} : { advisories };
|
|
34869
|
+
}
|
|
34804
34870
|
/**
|
|
34805
34871
|
* The images a sweep's shipped images build on that it could not read, and
|
|
34806
34872
|
* why (PRO-4073): a base nobody read is no clean base. Only where the API
|
|
@@ -34930,7 +34996,8 @@ async function sweepOverview(client, productId) {
|
|
|
34930
34996
|
const [summary, sweeps] = await Promise.all([client.getMaintenanceSummary(productId), client.listMaintenanceSweeps(productId, { limit: 3 })]);
|
|
34931
34997
|
const latest = sweeps.data.map((sweep) => ({
|
|
34932
34998
|
...pickFields([sweep], SWEEP_FIELDS)[0],
|
|
34933
|
-
...notReadBases(sweep)
|
|
34999
|
+
...notReadBases(sweep),
|
|
35000
|
+
...startedByAdvisories(sweep)
|
|
34934
35001
|
}));
|
|
34935
35002
|
const { lastRun: _lastRun, lastRuns: _lastRuns, topFindings: _top, violatedControls: _controls, ...counts } = summary.data;
|
|
34936
35003
|
return {
|
|
@@ -35097,7 +35164,7 @@ function registerMaintenanceTools(server, client) {
|
|
|
35097
35164
|
}, (params) => runTool(async () => toolResult({ notices: await client.getNotices(params.productId, params.linkId) })));
|
|
35098
35165
|
server.registerTool("taiga_get_finding", {
|
|
35099
35166
|
title: "Get a maintenance finding",
|
|
35100
|
-
description: "Read one finding: how likely it is to be exploited, the advisory and its fixed version, where it is, which policy controls it breaches,
|
|
35167
|
+
description: "Read one finding: how likely it is to be exploited, the advisory and its fixed version, where it is, which policy controls it breaches, any fix under way, and triage: whether the code reaches it, as its factory judged it at a commit (advice; it never changes the status). fixable: false says taiga_fix_finding would refuse it. A secret's value is never stored.",
|
|
35101
35168
|
inputSchema: object({
|
|
35102
35169
|
findingId,
|
|
35103
35170
|
full: boolean().optional().describe("Carry the advisory's whole record: every affected range and reference (default false)")
|
|
@@ -35240,6 +35307,21 @@ function registerMaintenanceTools(server, client) {
|
|
|
35240
35307
|
...params.expiresAt !== void 0 ? { ignoreExpiresAt: params.expiresAt } : {}
|
|
35241
35308
|
})).data);
|
|
35242
35309
|
}));
|
|
35310
|
+
server.registerTool("taiga_start_sweep", {
|
|
35311
|
+
title: "Sweep a repository",
|
|
35312
|
+
description: "Scan one of a product's repositories now: its dependencies, secrets, code and infrastructure, the findings triaged and its code judged against the policies. Its primary repository when none is named. Returns the sweep; taiga_list_findings and taiga_get_policy_standing read what it found once it completes.",
|
|
35313
|
+
inputSchema: object({
|
|
35314
|
+
productId,
|
|
35315
|
+
linkId: idInput("repository link", "taiga_list_product_repositories gives it (its id); a linkable repository id is not one").optional()
|
|
35316
|
+
}),
|
|
35317
|
+
annotations: OPERATE
|
|
35318
|
+
}, (params) => runTool(async () => {
|
|
35319
|
+
const { id, ...run } = (await client.startSweep(params.productId, params.linkId)).data;
|
|
35320
|
+
return toolResult({
|
|
35321
|
+
sweepId: id,
|
|
35322
|
+
...run
|
|
35323
|
+
});
|
|
35324
|
+
}));
|
|
35243
35325
|
server.registerTool("taiga_fix_finding", {
|
|
35244
35326
|
title: "Fix a finding",
|
|
35245
35327
|
description: "Raise an initiative that fixes a finding; it ends in a pull request, which merges on its own only where the product's auto-merge allows it. wholeGroup: true fixes, in that repository, every open advisory on that package version in one bump, or every place the rule flagged. A malicious package is removed, with every advisory on that version, whatever wholeGroup says. A license finding the row marks fixable has its packages replaced by ones on the approved list. A language runtime moves every file declaring it together, in a container image only to a tag the image has published. Refused when there is no version to move to (fixable: false; for a runtime, also while its image has not published the fix), the code is in a submodule, or a secret is only in history (rotate it outside Taiga).",
|
|
@@ -35723,7 +35805,7 @@ const PRODUCT_VIEW_FIELDS = [
|
|
|
35723
35805
|
"createdAt",
|
|
35724
35806
|
"updatedAt"
|
|
35725
35807
|
];
|
|
35726
|
-
const UNSET_MEANS = "A null setting is unset: kind reads as application; autoMerge follows the factory, then the organization; ownsInfrastructure and ownsDeployment follow the organization default (yes when it has none); ownsApplication is yes; emitDesignStandards follows how the product started; networkAccess is
|
|
35808
|
+
const UNSET_MEANS = "A null setting is unset: kind reads as application; autoMerge follows the factory, then the organization; ownsInfrastructure and ownsDeployment follow the organization default (yes when it has none); ownsApplication is yes; emitDesignStandards follows how the product started; networkAccess is unrestricted. signalAutonomy is what each kind of finding resolves to (off, notify, propose, build, merge) and what decided it: the product, the kind default or cap, or auto-merge consent. dailyFixLimit is how many fixes Taiga may raise on its own per day, set by the product or the starting value (setBy default).";
|
|
35727
35809
|
/**
|
|
35728
35810
|
* Each product's policy standing beside its row: the counts the standing read opens with. A product still in setup
|
|
35729
35811
|
* has none to read; a read the API refuses or fails says so on its row rather than failing the list.
|
|
@@ -36752,13 +36834,14 @@ function changeRequestRef(provider, number) {
|
|
|
36752
36834
|
}
|
|
36753
36835
|
/** What a person does about a handback, by its reason, as the web's handback detail says it, on the run's forge. */
|
|
36754
36836
|
function handbackNextStep(escalation, provider = null) {
|
|
36755
|
-
const
|
|
36756
|
-
const
|
|
36837
|
+
const forge = forgeOf({ provider });
|
|
36838
|
+
const terms = FORGE_TERMS[forge ?? "github"];
|
|
36839
|
+
const where = forge ? ` on ${terms.name}` : "";
|
|
36757
36840
|
const changeRequest = terms.changeRequest;
|
|
36758
36841
|
const reason = escalation && typeof escalation === "object" ? escalation.reason : null;
|
|
36759
|
-
if (reason === "check_weakened") return `review that change
|
|
36760
|
-
if (reason === "ci_never_settled") return `look at what is still running or queued in CI
|
|
36761
|
-
return `fix it by hand, or review the ${changeRequest}
|
|
36842
|
+
if (reason === "check_weakened") return `review that change${where} before merging`;
|
|
36843
|
+
if (reason === "ci_never_settled") return `look at what is still running or queued in CI${where}, then review the ${changeRequest}`;
|
|
36844
|
+
return `fix it by hand, or review the ${changeRequest}${where}, which hands it back to the agent`;
|
|
36762
36845
|
}
|
|
36763
36846
|
/** The web's words for why Taiga keeps a pull request a draft. */
|
|
36764
36847
|
const READY_BLOCKER_SAID = {
|
|
@@ -37197,14 +37280,21 @@ function registerBuildTools(server, client) {
|
|
|
37197
37280
|
}));
|
|
37198
37281
|
server.registerTool("taiga_get_run", {
|
|
37199
37282
|
title: "Get run",
|
|
37200
|
-
description: "Read one coding agent run, and why it failed when it did: its outcome, pull request, security pass (scanCoverage names scanners that did not run) and each step with its commit, files and checks. A failed run says where it stopped (stoppedIn) and the line of the error that says why (cause). full: true adds every step's instructions and report. lastReplan says what a request for changes did to the plan the run builds now: the steps it added, edited and dropped. A failed or stopped run's nextStep says how to carry it on (taiga_resume_initiative on its initiative).",
|
|
37283
|
+
description: "Read one coding agent run, and why it failed when it did: its outcome, pull request, security pass (scanCoverage names scanners that did not run) and each step with its commit, files and checks. A failed run says where it stopped (stoppedIn) and the line of the error that says why (cause). full: true adds every step's instructions and report. lastReplan says what a request for changes did to the plan the run builds now: the steps it added, edited and dropped. A failed or stopped run's nextStep says how to carry it on (taiga_resume_initiative on its initiative). hostsReached lists the public hosts the run reached through the egress gateway, first reached first, with the bytes it sent and received there.",
|
|
37201
37284
|
inputSchema: object({
|
|
37202
37285
|
runId,
|
|
37203
37286
|
full: boolean().optional().describe("Carry each step's complete instructions and report (default false: a summary)")
|
|
37204
37287
|
}),
|
|
37205
37288
|
annotations: READ_ONLY
|
|
37206
37289
|
}, (params) => runTool(async () => {
|
|
37207
|
-
const [run, steps] = await Promise.all([
|
|
37290
|
+
const [run, steps, hosts] = await Promise.all([
|
|
37291
|
+
client.getBuildRun(params.runId),
|
|
37292
|
+
client.listBuildRunSteps(params.runId),
|
|
37293
|
+
client.listBuildRunEgressHosts(params.runId).catch((error) => {
|
|
37294
|
+
if (error instanceof TaigaApiError && error.status === 404) return { data: [] };
|
|
37295
|
+
throw error;
|
|
37296
|
+
})
|
|
37297
|
+
]);
|
|
37208
37298
|
const runRow = run.data;
|
|
37209
37299
|
const rows = steps.data.map((step) => neverStarted(step));
|
|
37210
37300
|
const where = stoppedIn(runRow, rows);
|
|
@@ -37222,7 +37312,8 @@ function registerBuildTools(server, client) {
|
|
|
37222
37312
|
...lastReplan ? { lastReplan: {
|
|
37223
37313
|
...lastReplan,
|
|
37224
37314
|
waitsForReview
|
|
37225
|
-
} } : {}
|
|
37315
|
+
} } : {},
|
|
37316
|
+
...hostsReachedOf(hosts.data)
|
|
37226
37317
|
};
|
|
37227
37318
|
const note = verificationNote(rows);
|
|
37228
37319
|
const verification = note ? { verificationNote: note } : {};
|
|
@@ -37282,6 +37373,22 @@ function steerSituation(steer) {
|
|
|
37282
37373
|
if (steer === "after_round") return "The run is answering review comments or fixing CI; the request is planned when that round ends, and no further automatic round starts while it is open.";
|
|
37283
37374
|
return "A re-plan is already running; the request joins it.";
|
|
37284
37375
|
}
|
|
37376
|
+
/** At most this many hosts in a run's read; the rest are counted. */
|
|
37377
|
+
const HOSTS_REACHED_SHOWN = 50;
|
|
37378
|
+
/** Where a run went (PRO-4268): its hosts, first reached first, or nothing for a run that reached none. */
|
|
37379
|
+
function hostsReachedOf(hosts) {
|
|
37380
|
+
if (hosts.length === 0) return {};
|
|
37381
|
+
const shown = hosts.slice(0, HOSTS_REACHED_SHOWN).map(({ host, sentBytes, receivedBytes, connections }) => ({
|
|
37382
|
+
host,
|
|
37383
|
+
sentBytes,
|
|
37384
|
+
receivedBytes,
|
|
37385
|
+
connections
|
|
37386
|
+
}));
|
|
37387
|
+
return {
|
|
37388
|
+
hostsReached: shown,
|
|
37389
|
+
...hosts.length > shown.length ? { hostsReachedNotShown: hosts.length - shown.length } : {}
|
|
37390
|
+
};
|
|
37391
|
+
}
|
|
37285
37392
|
//#endregion
|
|
37286
37393
|
//#region src/tools/queue.ts
|
|
37287
37394
|
/** How many entries the read names; past this an entry keeps its initiativeId only. */
|
|
@@ -55408,7 +55515,7 @@ function registerSetupTools(server, client) {
|
|
|
55408
55515
|
}));
|
|
55409
55516
|
server.registerTool("taiga_update_product", {
|
|
55410
55517
|
title: "Change a product's settings",
|
|
55411
|
-
description: "Change a product's name, what Taiga builds for it (application, infrastructure, pipelines), or where its builds may connect (networkAccess: allowlist, Taiga's standard list plus the product's networkHosts
|
|
55518
|
+
description: "Change a product's name, what Taiga builds for it (application, infrastructure, pipelines), or where its builds may connect (networkAccess: unrestricted, any public host, the default; or allowlist, Taiga's standard list plus the product's networkHosts; networkHosts replaces the list, each one exact DNS name, no wildcard or domain anyone can host on, 100 at most; changes apply from the next build). A new name changes its slug. Later plans follow the change; planned work is not redone.",
|
|
55412
55519
|
inputSchema: object({
|
|
55413
55520
|
productId,
|
|
55414
55521
|
name: string$2().trim().min(1).max(255).optional().describe("A new name"),
|
|
@@ -55416,7 +55523,7 @@ function registerSetupTools(server, client) {
|
|
|
55416
55523
|
...buildScope,
|
|
55417
55524
|
deploymentNotes: deploymentNotes.nullable().optional(),
|
|
55418
55525
|
emitDesignStandards: boolean().nullable().optional().describe("Inherit the organization's design standards; null follows the default"),
|
|
55419
|
-
networkAccess: _enum(PRODUCT_NETWORK_ACCESS).nullable().optional().describe("Where a build's sandbox may connect:
|
|
55526
|
+
networkAccess: _enum(PRODUCT_NETWORK_ACCESS).nullable().optional().describe("Where a build's sandbox may connect: unrestricted (the default; null returns to it) or allowlist"),
|
|
55420
55527
|
networkHosts: array(string$2().trim().toLowerCase().min(1).max(253)).max(100).optional().describe("The product's own hosts beyond the standard list, replacing the current ones: exact DNS names such as api.example.com")
|
|
55421
55528
|
}),
|
|
55422
55529
|
annotations: OPERATE_SETTING
|
|
@@ -55724,6 +55831,7 @@ const PAID_WORK = /* @__PURE__ */ new Set([
|
|
|
55724
55831
|
"taiga_review_plan",
|
|
55725
55832
|
"taiga_set_auto_build",
|
|
55726
55833
|
"taiga_start_import",
|
|
55834
|
+
"taiga_start_sweep",
|
|
55727
55835
|
"taiga_stop_generating_documents",
|
|
55728
55836
|
"taiga_stop_run",
|
|
55729
55837
|
"taiga_sync_design_tokens"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taiga-ai/mcp-server",
|
|
3
|
-
"version": "0.37.0-rc.
|
|
3
|
+
"version": "0.37.0-rc.984",
|
|
4
4
|
"description": "Taiga for AI coding assistants: read products, policies, initiatives and runs, and operate the line, over MCP",
|
|
5
5
|
"mcpName": "ga.tai/mcp-server",
|
|
6
6
|
"license": "UNLICENSED",
|