@ttctl/mcp 0.0.0 → 0.1.0-rc.2
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 +72 -9
- package/dist/auth.d.ts +40 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +69 -0
- package/dist/auth.js.map +1 -0
- package/dist/data-handling.d.ts +91 -0
- package/dist/data-handling.d.ts.map +1 -0
- package/dist/data-handling.js +129 -0
- package/dist/data-handling.js.map +1 -0
- package/dist/diagnostic.d.ts +262 -0
- package/dist/diagnostic.d.ts.map +1 -0
- package/dist/diagnostic.js +362 -0
- package/dist/diagnostic.js.map +1 -0
- package/dist/errors.d.ts +54 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +48 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/kill-switch-hook.d.ts +67 -0
- package/dist/kill-switch-hook.d.ts.map +1 -0
- package/dist/kill-switch-hook.js +61 -0
- package/dist/kill-switch-hook.js.map +1 -0
- package/dist/server.d.ts +100 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +157 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/_shared.d.ts +227 -0
- package/dist/tools/_shared.d.ts.map +1 -0
- package/dist/tools/_shared.js +238 -0
- package/dist/tools/_shared.js.map +1 -0
- package/dist/tools/applications.d.ts +27 -0
- package/dist/tools/applications.d.ts.map +1 -0
- package/dist/tools/applications.js +192 -0
- package/dist/tools/applications.js.map +1 -0
- package/dist/tools/availability.d.ts +33 -0
- package/dist/tools/availability.d.ts.map +1 -0
- package/dist/tools/availability.js +272 -0
- package/dist/tools/availability.js.map +1 -0
- package/dist/tools/contracts.d.ts +29 -0
- package/dist/tools/contracts.d.ts.map +1 -0
- package/dist/tools/contracts.js +157 -0
- package/dist/tools/contracts.js.map +1 -0
- package/dist/tools/engagements.d.ts +36 -0
- package/dist/tools/engagements.d.ts.map +1 -0
- package/dist/tools/engagements.js +408 -0
- package/dist/tools/engagements.js.map +1 -0
- package/dist/tools/file-upload.d.ts +133 -0
- package/dist/tools/file-upload.d.ts.map +1 -0
- package/dist/tools/file-upload.js +247 -0
- package/dist/tools/file-upload.js.map +1 -0
- package/dist/tools/index.d.ts +28 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +133 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/jobs.d.ts +37 -0
- package/dist/tools/jobs.d.ts.map +1 -0
- package/dist/tools/jobs.js +505 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/output-schemas.d.ts +129 -0
- package/dist/tools/output-schemas.d.ts.map +1 -0
- package/dist/tools/output-schemas.js +138 -0
- package/dist/tools/output-schemas.js.map +1 -0
- package/dist/tools/payments.d.ts +36 -0
- package/dist/tools/payments.d.ts.map +1 -0
- package/dist/tools/payments.js +373 -0
- package/dist/tools/payments.js.map +1 -0
- package/dist/tools/profile/certifications.d.ts +18 -0
- package/dist/tools/profile/certifications.d.ts.map +1 -0
- package/dist/tools/profile/certifications.js +219 -0
- package/dist/tools/profile/certifications.js.map +1 -0
- package/dist/tools/profile/education.d.ts +23 -0
- package/dist/tools/profile/education.d.ts.map +1 -0
- package/dist/tools/profile/education.js +222 -0
- package/dist/tools/profile/education.js.map +1 -0
- package/dist/tools/profile/employment.d.ts +23 -0
- package/dist/tools/profile/employment.d.ts.map +1 -0
- package/dist/tools/profile/employment.js +254 -0
- package/dist/tools/profile/employment.js.map +1 -0
- package/dist/tools/profile/industries.d.ts +30 -0
- package/dist/tools/profile/industries.d.ts.map +1 -0
- package/dist/tools/profile/industries.js +196 -0
- package/dist/tools/profile/industries.js.map +1 -0
- package/dist/tools/profile/portfolio.d.ts +22 -0
- package/dist/tools/profile/portfolio.d.ts.map +1 -0
- package/dist/tools/profile/portfolio.js +341 -0
- package/dist/tools/profile/portfolio.js.map +1 -0
- package/dist/tools/profile/resume.d.ts +16 -0
- package/dist/tools/profile/resume.d.ts.map +1 -0
- package/dist/tools/profile/resume.js +107 -0
- package/dist/tools/profile/resume.js.map +1 -0
- package/dist/tools/profile/shared.d.ts +85 -0
- package/dist/tools/profile/shared.d.ts.map +1 -0
- package/dist/tools/profile/shared.js +128 -0
- package/dist/tools/profile/shared.js.map +1 -0
- package/dist/tools/profile/visas.d.ts +15 -0
- package/dist/tools/profile/visas.d.ts.map +1 -0
- package/dist/tools/profile/visas.js +170 -0
- package/dist/tools/profile/visas.js.map +1 -0
- package/dist/tools/profile_basic_photo_show.d.ts +14 -0
- package/dist/tools/profile_basic_photo_show.d.ts.map +1 -0
- package/dist/tools/profile_basic_photo_show.js +59 -0
- package/dist/tools/profile_basic_photo_show.js.map +1 -0
- package/dist/tools/profile_basic_photo_upload.d.ts +24 -0
- package/dist/tools/profile_basic_photo_upload.d.ts.map +1 -0
- package/dist/tools/profile_basic_photo_upload.js +90 -0
- package/dist/tools/profile_basic_photo_upload.js.map +1 -0
- package/dist/tools/profile_basic_show.d.ts +64 -0
- package/dist/tools/profile_basic_show.d.ts.map +1 -0
- package/dist/tools/profile_basic_show.js +108 -0
- package/dist/tools/profile_basic_show.js.map +1 -0
- package/dist/tools/profile_basic_update.d.ts +37 -0
- package/dist/tools/profile_basic_update.d.ts.map +1 -0
- package/dist/tools/profile_basic_update.js +97 -0
- package/dist/tools/profile_basic_update.js.map +1 -0
- package/dist/tools/profile_external_advanced_wizard_show.d.ts +14 -0
- package/dist/tools/profile_external_advanced_wizard_show.d.ts.map +1 -0
- package/dist/tools/profile_external_advanced_wizard_show.js +56 -0
- package/dist/tools/profile_external_advanced_wizard_show.js.map +1 -0
- package/dist/tools/profile_external_custom_requirements_set.d.ts +13 -0
- package/dist/tools/profile_external_custom_requirements_set.d.ts.map +1 -0
- package/dist/tools/profile_external_custom_requirements_set.js +75 -0
- package/dist/tools/profile_external_custom_requirements_set.js.map +1 -0
- package/dist/tools/profile_external_custom_requirements_show.d.ts +14 -0
- package/dist/tools/profile_external_custom_requirements_show.d.ts.map +1 -0
- package/dist/tools/profile_external_custom_requirements_show.js +56 -0
- package/dist/tools/profile_external_custom_requirements_show.js.map +1 -0
- package/dist/tools/profile_external_readiness.d.ts +12 -0
- package/dist/tools/profile_external_readiness.d.ts.map +1 -0
- package/dist/tools/profile_external_readiness.js +54 -0
- package/dist/tools/profile_external_readiness.js.map +1 -0
- package/dist/tools/profile_external_recommendations.d.ts +15 -0
- package/dist/tools/profile_external_recommendations.d.ts.map +1 -0
- package/dist/tools/profile_external_recommendations.js +57 -0
- package/dist/tools/profile_external_recommendations.js.map +1 -0
- package/dist/tools/profile_external_show.d.ts +15 -0
- package/dist/tools/profile_external_show.d.ts.map +1 -0
- package/dist/tools/profile_external_show.js +59 -0
- package/dist/tools/profile_external_show.js.map +1 -0
- package/dist/tools/profile_external_update.d.ts +14 -0
- package/dist/tools/profile_external_update.d.ts.map +1 -0
- package/dist/tools/profile_external_update.js +79 -0
- package/dist/tools/profile_external_update.js.map +1 -0
- package/dist/tools/profile_reviews_approve_item.d.ts +17 -0
- package/dist/tools/profile_reviews_approve_item.d.ts.map +1 -0
- package/dist/tools/profile_reviews_approve_item.js +77 -0
- package/dist/tools/profile_reviews_approve_item.js.map +1 -0
- package/dist/tools/profile_reviews_approve_section.d.ts +15 -0
- package/dist/tools/profile_reviews_approve_section.d.ts.map +1 -0
- package/dist/tools/profile_reviews_approve_section.js +70 -0
- package/dist/tools/profile_reviews_approve_section.js.map +1 -0
- package/dist/tools/profile_reviews_list.d.ts +16 -0
- package/dist/tools/profile_reviews_list.d.ts.map +1 -0
- package/dist/tools/profile_reviews_list.js +58 -0
- package/dist/tools/profile_reviews_list.js.map +1 -0
- package/dist/tools/profile_reviews_submit_for_review.d.ts +14 -0
- package/dist/tools/profile_reviews_submit_for_review.d.ts.map +1 -0
- package/dist/tools/profile_reviews_submit_for_review.js +56 -0
- package/dist/tools/profile_reviews_submit_for_review.js.map +1 -0
- package/dist/tools/profile_skills_add.d.ts +4 -0
- package/dist/tools/profile_skills_add.d.ts.map +1 -0
- package/dist/tools/profile_skills_add.js +52 -0
- package/dist/tools/profile_skills_add.js.map +1 -0
- package/dist/tools/profile_skills_autocomplete.d.ts +4 -0
- package/dist/tools/profile_skills_autocomplete.d.ts.map +1 -0
- package/dist/tools/profile_skills_autocomplete.js +78 -0
- package/dist/tools/profile_skills_autocomplete.js.map +1 -0
- package/dist/tools/profile_skills_list.d.ts +16 -0
- package/dist/tools/profile_skills_list.d.ts.map +1 -0
- package/dist/tools/profile_skills_list.js +65 -0
- package/dist/tools/profile_skills_list.js.map +1 -0
- package/dist/tools/profile_skills_readiness.d.ts +4 -0
- package/dist/tools/profile_skills_readiness.d.ts.map +1 -0
- package/dist/tools/profile_skills_readiness.js +53 -0
- package/dist/tools/profile_skills_readiness.js.map +1 -0
- package/dist/tools/profile_skills_remove.d.ts +4 -0
- package/dist/tools/profile_skills_remove.d.ts.map +1 -0
- package/dist/tools/profile_skills_remove.js +53 -0
- package/dist/tools/profile_skills_remove.js.map +1 -0
- package/dist/tools/profile_skills_show.d.ts +4 -0
- package/dist/tools/profile_skills_show.d.ts.map +1 -0
- package/dist/tools/profile_skills_show.js +51 -0
- package/dist/tools/profile_skills_show.js.map +1 -0
- package/dist/tools/profile_skills_update.d.ts +11 -0
- package/dist/tools/profile_skills_update.d.ts.map +1 -0
- package/dist/tools/profile_skills_update.js +97 -0
- package/dist/tools/profile_skills_update.js.map +1 -0
- package/dist/tools/timesheet.d.ts +29 -0
- package/dist/tools/timesheet.d.ts.map +1 -0
- package/dist/tools/timesheet.js +257 -0
- package/dist/tools/timesheet.js.map +1 -0
- package/package.json +33 -13
- package/index.js +0 -7
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { ConfigError } from "@ttctl/core";
|
|
2
|
+
import type { DryRunPreview, ToptalSurface } from "@ttctl/core";
|
|
3
|
+
import type { AuthResult } from "../auth.js";
|
|
4
|
+
import type { ToolErrorResponse } from "../errors.js";
|
|
5
|
+
/**
|
|
6
|
+
* Shared MCP-tool helpers — auth-token loading, response shaping, error
|
|
7
|
+
* mapping. Kept in one module so each `profile_basic_*` / `profile_skills_*`
|
|
8
|
+
* tool file stays small and focused on its own input shape.
|
|
9
|
+
*
|
|
10
|
+
* **Auth**: tools load the token per-call rather than caching it at server
|
|
11
|
+
* startup. The MCP server is a long-lived process; the user may re-run
|
|
12
|
+
* `ttctl auth signin` while the server is up, and the next tool call should
|
|
13
|
+
* pick up the new token without restarting the server.
|
|
14
|
+
*
|
|
15
|
+
* Post-#113: the per-call read targets the config path captured at
|
|
16
|
+
* `buildServer()` time, NOT a fresh per-invocation `resolveConfig()` call.
|
|
17
|
+
* Tools receive the bound `loadTokenForTool` closure via the registration
|
|
18
|
+
* context, not as a free import. Env-var shifts mid-session do not
|
|
19
|
+
* retarget reads or writes — the captured path is canonical for the
|
|
20
|
+
* session's lifetime.
|
|
21
|
+
*
|
|
22
|
+
* **Error contract**: domain failures (`ProfileError`, `SkillsError`) and
|
|
23
|
+
* typed `TtctlError` subclasses both render as MCP `isError: true` tool
|
|
24
|
+
* responses. Untyped throws bubble up to the SDK's default error path.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* MCP tool-success response shape. Mirrors the SDK's `CallToolResult`
|
|
28
|
+
* happy-path: a text-content array carrying the rendered payload.
|
|
29
|
+
*
|
|
30
|
+
* The `[key: string]: unknown` index signature keeps the type
|
|
31
|
+
* structurally compatible with the SDK's `CallToolResult` (whose own type
|
|
32
|
+
* carries the same signature for forward-compatibility with new optional
|
|
33
|
+
* fields). The `structuredContent` field is populated by
|
|
34
|
+
* {@link jsonResponse} so tools that declare an `outputSchema` (#226) get
|
|
35
|
+
* SDK-validated structured payload alongside the `text` slot.
|
|
36
|
+
* `structuredContent` is harmless metadata for tools without
|
|
37
|
+
* `outputSchema` — the SDK skips validation when `outputSchema` is
|
|
38
|
+
* absent.
|
|
39
|
+
*/
|
|
40
|
+
export interface ToolSuccessResponse {
|
|
41
|
+
content: [{
|
|
42
|
+
type: "text";
|
|
43
|
+
text: string;
|
|
44
|
+
}];
|
|
45
|
+
structuredContent?: Record<string, unknown>;
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Render a JSON-shaped payload as a tool-success response. Stringifies
|
|
50
|
+
* with two-space indentation so LLM clients see an easy-to-read response,
|
|
51
|
+
* and mirrors the payload into `structuredContent` so tools that declare
|
|
52
|
+
* an `outputSchema` (#226) get SDK-validated structured output without
|
|
53
|
+
* each tool having to plumb the field manually.
|
|
54
|
+
*
|
|
55
|
+
* `structuredContent` is only populated when `payload` is an object — the
|
|
56
|
+
* MCP SDK's `structuredContent` slot expects an object shape per
|
|
57
|
+
* `CallToolResult`, and arrays / primitives are encoded only via the
|
|
58
|
+
* `text` slot (callers that emit array payloads can still validate the
|
|
59
|
+
* JSON-decoded `text` field client-side).
|
|
60
|
+
*/
|
|
61
|
+
export declare function jsonResponse(payload: unknown): ToolSuccessResponse;
|
|
62
|
+
/**
|
|
63
|
+
* Render a plain string as a tool-success response (e.g., for tools that
|
|
64
|
+
* return a confirmation rather than structured data). Use
|
|
65
|
+
* {@link textWithStructuredResponse} when both a human-readable line and
|
|
66
|
+
* a typed acknowledgment are desired (e.g., `*_remove` tools per #226).
|
|
67
|
+
*/
|
|
68
|
+
export declare function textResponse(text: string): ToolSuccessResponse;
|
|
69
|
+
/**
|
|
70
|
+
* Render a confirmation line as the `text` content slot while also
|
|
71
|
+
* publishing a typed acknowledgment via `structuredContent`. Used by
|
|
72
|
+
* `*_remove` tools (#226) where the human-readable text stays for
|
|
73
|
+
* compatibility and the structured payload is `{ id, removed: true }`
|
|
74
|
+
* matching the tool's declared `outputSchema`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function textWithStructuredResponse(text: string, structuredContent: Record<string, unknown>): ToolSuccessResponse;
|
|
77
|
+
/**
|
|
78
|
+
* Uniform MCP dry-run response envelope (issue #165). Every tool's
|
|
79
|
+
* `dryRun: true` branch renders through this so MCP clients can treat
|
|
80
|
+
* `dryRun` as a universal "preview" affordance without per-tool envelope
|
|
81
|
+
* knowledge. The shape is `{ ok: true, dryRun: true, preview }` where
|
|
82
|
+
* `preview` is the canonical {@link DryRunPreview} carrying surface,
|
|
83
|
+
* transport, endpoint, operationName, variables, and (bearer-redacted)
|
|
84
|
+
* headers. The same envelope is emitted whether the preview was
|
|
85
|
+
* constructed at the MCP layer (via {@link buildMcpDryRunPreview}) or
|
|
86
|
+
* received from a core service whose `dryRun` option is supported
|
|
87
|
+
* (`profile.basic.set`, `jobs.*`, `engagements.breaks.*`,
|
|
88
|
+
* `availability.*Set`).
|
|
89
|
+
*/
|
|
90
|
+
export declare function dryRunResponse(preview: DryRunPreview): ToolSuccessResponse;
|
|
91
|
+
/**
|
|
92
|
+
* Sibling envelope for multi-mutation tools (issue #165). Some tools fire
|
|
93
|
+
* MORE than one wire operation per invocation — `profile.skills.update`
|
|
94
|
+
* fires one mutation per supplied field (rating, experience, publicity).
|
|
95
|
+
* Single-preview envelope would lie: a caller previewing
|
|
96
|
+
* `update({id, rating, experience})` with the singular envelope would see
|
|
97
|
+
* one mutation while the apply path would actually fire two.
|
|
98
|
+
*
|
|
99
|
+
* The plural form preserves honesty without diverging from the dry-run
|
|
100
|
+
* contract: same `{ ok: true, dryRun: true, ... }` shape, but the `preview`
|
|
101
|
+
* key is replaced by `previews` (array). Tools using this helper MUST
|
|
102
|
+
* document the plural form on the tool description so MCP clients can
|
|
103
|
+
* branch on shape. The cross-cutting dry-run smoke test (#165 AC)
|
|
104
|
+
* accepts EITHER `preview` (single) OR `previews` (array).
|
|
105
|
+
*/
|
|
106
|
+
export declare function dryRunMultiResponse(previews: DryRunPreview[]): ToolSuccessResponse;
|
|
107
|
+
/**
|
|
108
|
+
* Build a {@link DryRunPreview} at the MCP layer for tools whose core
|
|
109
|
+
* service does NOT carry its own `dryRun` option — i.e. read-only tools
|
|
110
|
+
* across every group and the profile sub-domains beyond `profile.basic`
|
|
111
|
+
* (`skills`, `industries`, `education`, `certifications`, `employment`,
|
|
112
|
+
* `portfolio`, `visas`, `resume`, `external`, `reviews`). The MCP tool
|
|
113
|
+
* supplies the operation's metadata + would-be variables; the helper
|
|
114
|
+
* constructs the preview via the public {@link buildDryRunPreview}
|
|
115
|
+
* primitive without invoking any transport (read or write).
|
|
116
|
+
*
|
|
117
|
+
* For mutating tools whose core supports `dryRun` (the four exceptions
|
|
118
|
+
* listed above), prefer passing `{ dryRun: true }` through to the core
|
|
119
|
+
* call and branching on the returned `{ kind: "preview", preview }`
|
|
120
|
+
* outcome — that path reuses the canonical variable-construction
|
|
121
|
+
* (including placeholder substitution for fields like `profileId` that
|
|
122
|
+
* would otherwise be resolved via a sibling read) and avoids drift
|
|
123
|
+
* between MCP-built variables and what core would actually send.
|
|
124
|
+
*
|
|
125
|
+
* The `token` is forwarded as `authToken` on the synthesised
|
|
126
|
+
* {@link TransportRequest} so {@link buildDryRunPreview} sets the
|
|
127
|
+
* `authorization` header to {@link DRY_RUN_REDACTED_AUTHORIZATION}
|
|
128
|
+
* (i.e. `Token token=<redacted>`) without ever placing the live bearer
|
|
129
|
+
* in the preview payload.
|
|
130
|
+
*/
|
|
131
|
+
export declare function buildMcpDryRunPreview(operationName: string, surface: ToptalSurface, variables: Record<string, unknown>, token: string): DryRunPreview;
|
|
132
|
+
/**
|
|
133
|
+
* Build a tool-error response for a missing / unreadable auth token. The
|
|
134
|
+
* MCP equivalent of the CLI's `(UNAUTHENTICATED): No auth token found`
|
|
135
|
+
* branch.
|
|
136
|
+
*/
|
|
137
|
+
export declare function unauthenticatedResponse(toolName: string): ToolErrorResponse;
|
|
138
|
+
/**
|
|
139
|
+
* Build a tool-error response for a config-resolution or write-back
|
|
140
|
+
* failure. The `ConfigError.code` discriminator (`NO_CREDS` / `PARSE` /
|
|
141
|
+
* `VALIDATION` / `PERMISSION` / `LOCKED`) is surfaced verbatim as the
|
|
142
|
+
* wire-format code so MCP clients can branch on it without string-matching
|
|
143
|
+
* the prose message. `LOCKED` indicates another ttctl process holds the
|
|
144
|
+
* config write-back lock — the MCP client should retry after a brief delay.
|
|
145
|
+
*/
|
|
146
|
+
export declare function configErrorResponse(toolName: string, err: ConfigError): ToolErrorResponse;
|
|
147
|
+
/**
|
|
148
|
+
* Build a tool-error response for a domain error carrying a `code` +
|
|
149
|
+
* `message`. Used for `ProfileError` and `SkillsError` — both expose the
|
|
150
|
+
* same shape (`{code, message}`) but live in different modules.
|
|
151
|
+
*/
|
|
152
|
+
export declare function domainErrorResponse(toolName: string, err: {
|
|
153
|
+
code: string;
|
|
154
|
+
message: string;
|
|
155
|
+
}): ToolErrorResponse;
|
|
156
|
+
/**
|
|
157
|
+
* Build a tool-error response for an unexpected exception (anything that
|
|
158
|
+
* isn't a `TtctlError` or domain error). Surfaced so the LLM client gets
|
|
159
|
+
* a structured response rather than the SDK's untyped error fallback.
|
|
160
|
+
*/
|
|
161
|
+
export declare function genericErrorResponse(toolName: string, err: unknown): ToolErrorResponse;
|
|
162
|
+
/**
|
|
163
|
+
* Shared auth-token loader. Returns either the token (string) or a
|
|
164
|
+
* tool-error response that the caller should return verbatim.
|
|
165
|
+
*
|
|
166
|
+
* Routes via `ttctlErrorToToolResponseOrNull` first so any `TtctlError`
|
|
167
|
+
* thrown by the resolver chain (rare but possible) gets the uniform
|
|
168
|
+
* Error/Recovery/Code rendering.
|
|
169
|
+
*
|
|
170
|
+
* The loader is a factory closure over the MCP session's canonical config
|
|
171
|
+
* path captured at startup (#113). Per-call reads always target that path;
|
|
172
|
+
* env-var shifts during the session do NOT retarget the read.
|
|
173
|
+
*/
|
|
174
|
+
export type TokenLoader = (toolName: string) => Promise<{
|
|
175
|
+
token: string;
|
|
176
|
+
} | ToolErrorResponse>;
|
|
177
|
+
export declare function createTokenLoader(configPath: string): TokenLoader;
|
|
178
|
+
/**
|
|
179
|
+
* Type guard: true when `value` is one of our tool responses (success or
|
|
180
|
+
* error). Used by tool handlers to decide whether to short-circuit on a
|
|
181
|
+
* failed token load.
|
|
182
|
+
*/
|
|
183
|
+
export declare function isToolErrorResponse(value: unknown): value is ToolErrorResponse;
|
|
184
|
+
/**
|
|
185
|
+
* Resolver-shape used by `tools/profile/shared.ts` (`commandLabel`-flavored
|
|
186
|
+
* auth resolution returning `{token} | {error}`). Defined here so the
|
|
187
|
+
* `ToolRegistrationContext` can carry it without `_shared.ts` having to
|
|
188
|
+
* import from `tools/profile/`.
|
|
189
|
+
*/
|
|
190
|
+
export type TokenResolver = (commandLabel: string) => Promise<{
|
|
191
|
+
token: string;
|
|
192
|
+
} | {
|
|
193
|
+
error: ToolErrorResponse;
|
|
194
|
+
}>;
|
|
195
|
+
/**
|
|
196
|
+
* Dependency-injection context threaded through `registerAllTools` (#113).
|
|
197
|
+
*
|
|
198
|
+
* `buildServer({configPath})` calls `resolveConfig` ONCE at startup and
|
|
199
|
+
* uses the resulting absolute path to construct each resolver. The
|
|
200
|
+
* context is then handed to `registerAllTools`, which forwards it to each
|
|
201
|
+
* per-tool registrar so per-tool callbacks invoke `ctx.resolveToolAuth()`
|
|
202
|
+
* / `ctx.loadTokenForTool(toolName)` / `ctx.resolveTokenForTool(label)`
|
|
203
|
+
* instead of free-importing module-scoped functions that would re-resolve
|
|
204
|
+
* config (and re-read env) on each call.
|
|
205
|
+
*
|
|
206
|
+
* Three resolver shapes co-exist because the existing tool surface uses
|
|
207
|
+
* three different conventions:
|
|
208
|
+
*
|
|
209
|
+
* - `resolveToolAuth` — discriminated-union `AuthResult`
|
|
210
|
+
* (`{ok: true, token} | {ok: false, response}`) consumed by
|
|
211
|
+
* `tools/profile/portfolio|resume|visas.ts`.
|
|
212
|
+
* - `loadTokenForTool(toolName)` — toolName-aware error path that
|
|
213
|
+
* includes the tool name in the rendered `Error: <toolName> failed
|
|
214
|
+
* (...)` text. Used by every per-file `profile_*_*.ts` tool.
|
|
215
|
+
* - `resolveTokenForTool(commandLabel)` — `commandLabel`-prefixed errors
|
|
216
|
+
* (`{token} | {error}` shape) used by sub-domain registrars in
|
|
217
|
+
* `tools/profile/certifications|education|employment|industries.ts`.
|
|
218
|
+
*
|
|
219
|
+
* All three target the captured configPath; mid-session env shifts do
|
|
220
|
+
* NOT retarget reads or writes for any of the three.
|
|
221
|
+
*/
|
|
222
|
+
export interface ToolRegistrationContext {
|
|
223
|
+
resolveToolAuth: () => Promise<AuthResult>;
|
|
224
|
+
loadTokenForTool: TokenLoader;
|
|
225
|
+
resolveTokenForTool: TokenResolver;
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=_shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAiD,MAAM,aAAa,CAAC;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAQlE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACzC,mBAAmB,CAKrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,mBAAmB,CAc1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,mBAAmB,CAQlF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,KAAK,EAAE,MAAM,GACZ,aAAa,CAMf;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAU3E;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,iBAAiB,CAUzF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,iBAAiB,CAU/G;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAWtF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,iBAAiB,CAAC,CAAC;AAE/F,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CA2BjE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAAC;AAEhH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,gBAAgB,EAAE,WAAW,CAAC;IAC9B,mBAAmB,EAAE,aAAa,CAAC;CACpC"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
import { ConfigError, TtctlError, buildDryRunPreview, resolveConfig } from "@ttctl/core";
|
|
4
|
+
import { emitMcpAuthResolve } from "../diagnostic.js";
|
|
5
|
+
import { ttctlErrorToToolResponseOrNull } from "../errors.js";
|
|
6
|
+
/**
|
|
7
|
+
* Render a JSON-shaped payload as a tool-success response. Stringifies
|
|
8
|
+
* with two-space indentation so LLM clients see an easy-to-read response,
|
|
9
|
+
* and mirrors the payload into `structuredContent` so tools that declare
|
|
10
|
+
* an `outputSchema` (#226) get SDK-validated structured output without
|
|
11
|
+
* each tool having to plumb the field manually.
|
|
12
|
+
*
|
|
13
|
+
* `structuredContent` is only populated when `payload` is an object — the
|
|
14
|
+
* MCP SDK's `structuredContent` slot expects an object shape per
|
|
15
|
+
* `CallToolResult`, and arrays / primitives are encoded only via the
|
|
16
|
+
* `text` slot (callers that emit array payloads can still validate the
|
|
17
|
+
* JSON-decoded `text` field client-side).
|
|
18
|
+
*/
|
|
19
|
+
export function jsonResponse(payload) {
|
|
20
|
+
const response = {
|
|
21
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
|
|
22
|
+
};
|
|
23
|
+
if (payload !== null && typeof payload === "object" && !Array.isArray(payload)) {
|
|
24
|
+
response.structuredContent = payload;
|
|
25
|
+
}
|
|
26
|
+
return response;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Render a plain string as a tool-success response (e.g., for tools that
|
|
30
|
+
* return a confirmation rather than structured data). Use
|
|
31
|
+
* {@link textWithStructuredResponse} when both a human-readable line and
|
|
32
|
+
* a typed acknowledgment are desired (e.g., `*_remove` tools per #226).
|
|
33
|
+
*/
|
|
34
|
+
export function textResponse(text) {
|
|
35
|
+
return { content: [{ type: "text", text }] };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Render a confirmation line as the `text` content slot while also
|
|
39
|
+
* publishing a typed acknowledgment via `structuredContent`. Used by
|
|
40
|
+
* `*_remove` tools (#226) where the human-readable text stays for
|
|
41
|
+
* compatibility and the structured payload is `{ id, removed: true }`
|
|
42
|
+
* matching the tool's declared `outputSchema`.
|
|
43
|
+
*/
|
|
44
|
+
export function textWithStructuredResponse(text, structuredContent) {
|
|
45
|
+
return {
|
|
46
|
+
content: [{ type: "text", text }],
|
|
47
|
+
structuredContent,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Uniform MCP dry-run response envelope (issue #165). Every tool's
|
|
52
|
+
* `dryRun: true` branch renders through this so MCP clients can treat
|
|
53
|
+
* `dryRun` as a universal "preview" affordance without per-tool envelope
|
|
54
|
+
* knowledge. The shape is `{ ok: true, dryRun: true, preview }` where
|
|
55
|
+
* `preview` is the canonical {@link DryRunPreview} carrying surface,
|
|
56
|
+
* transport, endpoint, operationName, variables, and (bearer-redacted)
|
|
57
|
+
* headers. The same envelope is emitted whether the preview was
|
|
58
|
+
* constructed at the MCP layer (via {@link buildMcpDryRunPreview}) or
|
|
59
|
+
* received from a core service whose `dryRun` option is supported
|
|
60
|
+
* (`profile.basic.set`, `jobs.*`, `engagements.breaks.*`,
|
|
61
|
+
* `availability.*Set`).
|
|
62
|
+
*/
|
|
63
|
+
export function dryRunResponse(preview) {
|
|
64
|
+
// Intentionally emits ONLY the `text` content slot — no
|
|
65
|
+
// `structuredContent`. The dry-run envelope shape does NOT match the
|
|
66
|
+
// success-path `outputSchema` declared by #226 tools, and the MCP SDK
|
|
67
|
+
// validates `structuredContent` against `outputSchema` when both are
|
|
68
|
+
// present. Leaving `structuredContent` absent lets the SDK skip
|
|
69
|
+
// validation for dry-run responses (per `_validateOutput`: "if
|
|
70
|
+
// `!result.structuredContent` return"), preserving the universal
|
|
71
|
+
// `{ ok, dryRun, preview }` envelope contract without forcing every
|
|
72
|
+
// tool's `outputSchema` to absorb the dry-run shape.
|
|
73
|
+
const envelope = { ok: true, dryRun: true, preview };
|
|
74
|
+
return {
|
|
75
|
+
content: [{ type: "text", text: JSON.stringify(envelope, null, 2) }],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sibling envelope for multi-mutation tools (issue #165). Some tools fire
|
|
80
|
+
* MORE than one wire operation per invocation — `profile.skills.update`
|
|
81
|
+
* fires one mutation per supplied field (rating, experience, publicity).
|
|
82
|
+
* Single-preview envelope would lie: a caller previewing
|
|
83
|
+
* `update({id, rating, experience})` with the singular envelope would see
|
|
84
|
+
* one mutation while the apply path would actually fire two.
|
|
85
|
+
*
|
|
86
|
+
* The plural form preserves honesty without diverging from the dry-run
|
|
87
|
+
* contract: same `{ ok: true, dryRun: true, ... }` shape, but the `preview`
|
|
88
|
+
* key is replaced by `previews` (array). Tools using this helper MUST
|
|
89
|
+
* document the plural form on the tool description so MCP clients can
|
|
90
|
+
* branch on shape. The cross-cutting dry-run smoke test (#165 AC)
|
|
91
|
+
* accepts EITHER `preview` (single) OR `previews` (array).
|
|
92
|
+
*/
|
|
93
|
+
export function dryRunMultiResponse(previews) {
|
|
94
|
+
// Same rationale as `dryRunResponse` — emits ONLY `content`, no
|
|
95
|
+
// `structuredContent`, so #226 tools with declared `outputSchema`
|
|
96
|
+
// don't fail validation on the dry-run shape.
|
|
97
|
+
const envelope = { ok: true, dryRun: true, previews };
|
|
98
|
+
return {
|
|
99
|
+
content: [{ type: "text", text: JSON.stringify(envelope, null, 2) }],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Build a {@link DryRunPreview} at the MCP layer for tools whose core
|
|
104
|
+
* service does NOT carry its own `dryRun` option — i.e. read-only tools
|
|
105
|
+
* across every group and the profile sub-domains beyond `profile.basic`
|
|
106
|
+
* (`skills`, `industries`, `education`, `certifications`, `employment`,
|
|
107
|
+
* `portfolio`, `visas`, `resume`, `external`, `reviews`). The MCP tool
|
|
108
|
+
* supplies the operation's metadata + would-be variables; the helper
|
|
109
|
+
* constructs the preview via the public {@link buildDryRunPreview}
|
|
110
|
+
* primitive without invoking any transport (read or write).
|
|
111
|
+
*
|
|
112
|
+
* For mutating tools whose core supports `dryRun` (the four exceptions
|
|
113
|
+
* listed above), prefer passing `{ dryRun: true }` through to the core
|
|
114
|
+
* call and branching on the returned `{ kind: "preview", preview }`
|
|
115
|
+
* outcome — that path reuses the canonical variable-construction
|
|
116
|
+
* (including placeholder substitution for fields like `profileId` that
|
|
117
|
+
* would otherwise be resolved via a sibling read) and avoids drift
|
|
118
|
+
* between MCP-built variables and what core would actually send.
|
|
119
|
+
*
|
|
120
|
+
* The `token` is forwarded as `authToken` on the synthesised
|
|
121
|
+
* {@link TransportRequest} so {@link buildDryRunPreview} sets the
|
|
122
|
+
* `authorization` header to {@link DRY_RUN_REDACTED_AUTHORIZATION}
|
|
123
|
+
* (i.e. `Token token=<redacted>`) without ever placing the live bearer
|
|
124
|
+
* in the preview payload.
|
|
125
|
+
*/
|
|
126
|
+
export function buildMcpDryRunPreview(operationName, surface, variables, token) {
|
|
127
|
+
return buildDryRunPreview({
|
|
128
|
+
surface,
|
|
129
|
+
body: { operationName, variables },
|
|
130
|
+
authToken: token,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Build a tool-error response for a missing / unreadable auth token. The
|
|
135
|
+
* MCP equivalent of the CLI's `(UNAUTHENTICATED): No auth token found`
|
|
136
|
+
* branch.
|
|
137
|
+
*/
|
|
138
|
+
export function unauthenticatedResponse(toolName) {
|
|
139
|
+
return {
|
|
140
|
+
isError: true,
|
|
141
|
+
content: [
|
|
142
|
+
{
|
|
143
|
+
type: "text",
|
|
144
|
+
text: `Error: ${toolName} failed (UNAUTHENTICATED): No auth token found.\n\nRecovery: Run \`ttctl auth signin\` to sign in.\n\n(Code: UNAUTHENTICATED)`,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Build a tool-error response for a config-resolution or write-back
|
|
151
|
+
* failure. The `ConfigError.code` discriminator (`NO_CREDS` / `PARSE` /
|
|
152
|
+
* `VALIDATION` / `PERMISSION` / `LOCKED`) is surfaced verbatim as the
|
|
153
|
+
* wire-format code so MCP clients can branch on it without string-matching
|
|
154
|
+
* the prose message. `LOCKED` indicates another ttctl process holds the
|
|
155
|
+
* config write-back lock — the MCP client should retry after a brief delay.
|
|
156
|
+
*/
|
|
157
|
+
export function configErrorResponse(toolName, err) {
|
|
158
|
+
return {
|
|
159
|
+
isError: true,
|
|
160
|
+
content: [
|
|
161
|
+
{
|
|
162
|
+
type: "text",
|
|
163
|
+
text: `Error: ${toolName} failed (${err.code}): ${err.message}\n\n(Code: ${err.code})`,
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Build a tool-error response for a domain error carrying a `code` +
|
|
170
|
+
* `message`. Used for `ProfileError` and `SkillsError` — both expose the
|
|
171
|
+
* same shape (`{code, message}`) but live in different modules.
|
|
172
|
+
*/
|
|
173
|
+
export function domainErrorResponse(toolName, err) {
|
|
174
|
+
return {
|
|
175
|
+
isError: true,
|
|
176
|
+
content: [
|
|
177
|
+
{
|
|
178
|
+
type: "text",
|
|
179
|
+
text: `Error: ${toolName} failed (${err.code}): ${err.message}\n\n(Code: ${err.code})`,
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Build a tool-error response for an unexpected exception (anything that
|
|
186
|
+
* isn't a `TtctlError` or domain error). Surfaced so the LLM client gets
|
|
187
|
+
* a structured response rather than the SDK's untyped error fallback.
|
|
188
|
+
*/
|
|
189
|
+
export function genericErrorResponse(toolName, err) {
|
|
190
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
191
|
+
return {
|
|
192
|
+
isError: true,
|
|
193
|
+
content: [
|
|
194
|
+
{
|
|
195
|
+
type: "text",
|
|
196
|
+
text: `Error: ${toolName} failed: ${message}\n\n(Code: UNKNOWN)`,
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
export function createTokenLoader(configPath) {
|
|
202
|
+
return async function loadTokenForTool(toolName) {
|
|
203
|
+
let token;
|
|
204
|
+
try {
|
|
205
|
+
const { config } = resolveConfig({ path: configPath });
|
|
206
|
+
token = config.auth.token;
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
if (err instanceof ConfigError) {
|
|
210
|
+
emitMcpAuthResolve(configPath, "config_error", false);
|
|
211
|
+
return configErrorResponse(toolName, err);
|
|
212
|
+
}
|
|
213
|
+
if (err instanceof TtctlError) {
|
|
214
|
+
const typed = ttctlErrorToToolResponseOrNull(err);
|
|
215
|
+
if (typed !== null) {
|
|
216
|
+
emitMcpAuthResolve(configPath, "config_error", false);
|
|
217
|
+
return typed;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
throw err;
|
|
221
|
+
}
|
|
222
|
+
if (token === undefined) {
|
|
223
|
+
emitMcpAuthResolve(configPath, "unauthenticated", false);
|
|
224
|
+
return unauthenticatedResponse(toolName);
|
|
225
|
+
}
|
|
226
|
+
emitMcpAuthResolve(configPath, "ok", true);
|
|
227
|
+
return Promise.resolve({ token });
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Type guard: true when `value` is one of our tool responses (success or
|
|
232
|
+
* error). Used by tool handlers to decide whether to short-circuit on a
|
|
233
|
+
* failed token load.
|
|
234
|
+
*/
|
|
235
|
+
export function isToolErrorResponse(value) {
|
|
236
|
+
return typeof value === "object" && value !== null && "isError" in value && value.isError === true;
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=_shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { type ToolRegistrationContext } from "./_shared.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register the three `ttctl_applications_*` MCP tools per the #15 spec.
|
|
5
|
+
* Tool names use the `ttctl_` prefix and the canonical CLI path joined
|
|
6
|
+
* with `_` per project naming policy:
|
|
7
|
+
*
|
|
8
|
+
* - `ttctl_applications_list`
|
|
9
|
+
* - `ttctl_applications_show`
|
|
10
|
+
* - `ttctl_applications_stats`
|
|
11
|
+
*
|
|
12
|
+
* Each tool maps 1:1 to a CLI leaf — the schemas describe the same set
|
|
13
|
+
* of fields. The list tool's `keywords` and `statusGroups` mirror the
|
|
14
|
+
* `--keywords` / `--status-group` CLI flags.
|
|
15
|
+
*
|
|
16
|
+
* **Read-only** — per project non-goals (#15), no apply / withdraw /
|
|
17
|
+
* edit tools are exposed. `applications` is intentionally a smaller
|
|
18
|
+
* surface than the profile sub-domains.
|
|
19
|
+
*
|
|
20
|
+
* Dry-run path (issue #165): every tool accepts `dryRun?: boolean`.
|
|
21
|
+
* `list` and `show` emit the singular `{ preview }` envelope (one
|
|
22
|
+
* operation per call); `stats` emits the plural `{ previews: [...] }`
|
|
23
|
+
* envelope because the apply path fires 5 parallel `JobActivityItems`
|
|
24
|
+
* calls (one per STATUS_GROUPS member) — see {@link dryRunMultiResponse}.
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerApplicationsTools(server: McpServer, ctx: ToolRegistrationContext): void;
|
|
27
|
+
//# sourceMappingURL=applications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applications.d.ts","sourceRoot":"","sources":["../../src/tools/applications.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,OAAO,EAA8D,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AASxH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CAwH/F"}
|