@typeship-ax/mcp 0.19.0 → 0.21.0

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.
Files changed (103) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +1 -1
  3. package/api.json +7519 -6363
  4. package/api.md +8015 -6765
  5. package/dist/api-identity.d.ts.map +1 -1
  6. package/dist/api-identity.js +6 -1
  7. package/dist/core/http.d.ts +26 -14
  8. package/dist/core/http.d.ts.map +1 -1
  9. package/dist/core/http.js +90 -19
  10. package/dist/core/pagination.d.ts +8 -8
  11. package/dist/core/pagination.d.ts.map +1 -1
  12. package/dist/core/pagination.js +7 -16
  13. package/dist/errors.d.ts +4 -4
  14. package/dist/errors.d.ts.map +1 -1
  15. package/dist/errors.js +7 -7
  16. package/dist/index.d.ts +33 -19
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +37 -17
  19. package/dist/mcp-protocol.js +2 -2
  20. package/dist/mcp.d.ts.map +1 -1
  21. package/dist/mcp.js +6 -5
  22. package/dist/ops.d.ts +1 -1
  23. package/dist/ops.d.ts.map +1 -1
  24. package/dist/ops.js +40 -43
  25. package/dist/resources/api-keys.d.ts +16 -15
  26. package/dist/resources/api-keys.d.ts.map +1 -1
  27. package/dist/resources/api-keys.js +6 -6
  28. package/dist/resources/deliveries.d.ts +47 -0
  29. package/dist/resources/deliveries.d.ts.map +1 -0
  30. package/dist/resources/deliveries.js +70 -0
  31. package/dist/resources/drafts.d.ts +157 -0
  32. package/dist/resources/drafts.d.ts.map +1 -0
  33. package/dist/resources/drafts.js +230 -0
  34. package/dist/resources/files.d.ts +23 -0
  35. package/dist/resources/files.d.ts.map +1 -0
  36. package/dist/resources/files.js +38 -0
  37. package/dist/resources/generate.d.ts +14 -14
  38. package/dist/resources/generate.d.ts.map +1 -1
  39. package/dist/resources/generate.js +7 -7
  40. package/dist/resources/generations.d.ts +67 -21
  41. package/dist/resources/generations.d.ts.map +1 -1
  42. package/dist/resources/generations.js +67 -20
  43. package/dist/resources/organization.d.ts +18 -0
  44. package/dist/resources/organization.d.ts.map +1 -0
  45. package/dist/resources/{account.js → organization.js} +10 -10
  46. package/dist/resources/projects.d.ts +50 -139
  47. package/dist/resources/projects.d.ts.map +1 -1
  48. package/dist/resources/projects.js +29 -179
  49. package/dist/resources/publications.d.ts +47 -0
  50. package/dist/resources/publications.d.ts.map +1 -0
  51. package/dist/resources/publications.js +70 -0
  52. package/dist/resources/releases.d.ts +68 -0
  53. package/dist/resources/releases.d.ts.map +1 -0
  54. package/dist/resources/releases.js +102 -0
  55. package/dist/resources/spec-revisions.d.ts +87 -0
  56. package/dist/resources/spec-revisions.d.ts.map +1 -0
  57. package/dist/resources/spec-revisions.js +116 -0
  58. package/dist/resources/specs.d.ts +73 -0
  59. package/dist/resources/specs.d.ts.map +1 -0
  60. package/dist/resources/specs.js +108 -0
  61. package/dist/resources/targets.d.ts +48 -267
  62. package/dist/resources/targets.d.ts.map +1 -1
  63. package/dist/resources/targets.js +28 -407
  64. package/dist/schemas.d.ts.map +1 -1
  65. package/dist/schemas.js +143 -149
  66. package/dist/types.d.ts +1320 -1637
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/types.js +84 -76
  69. package/package.json +1 -1
  70. package/server.json +2 -2
  71. package/src/api-identity.ts +6 -2
  72. package/src/core/http.ts +89 -24
  73. package/src/core/pagination.ts +13 -23
  74. package/src/errors.ts +7 -7
  75. package/src/index.ts +41 -23
  76. package/src/mcp-protocol.ts +2 -2
  77. package/src/mcp.ts +7 -6
  78. package/src/ops.ts +41 -44
  79. package/src/resources/api-keys.ts +19 -21
  80. package/src/resources/deliveries.ts +140 -0
  81. package/src/resources/drafts.ts +424 -0
  82. package/src/resources/files.ts +68 -0
  83. package/src/resources/generate.ts +16 -19
  84. package/src/resources/generations.ts +148 -35
  85. package/src/resources/{account.ts → organization.ts} +14 -14
  86. package/src/resources/projects.ts +56 -350
  87. package/src/resources/publications.ts +140 -0
  88. package/src/resources/releases.ts +201 -0
  89. package/src/resources/spec-revisions.ts +239 -0
  90. package/src/resources/specs.ts +201 -0
  91. package/src/resources/targets.ts +63 -765
  92. package/src/schemas.ts +143 -149
  93. package/src/types.ts +1418 -1740
  94. package/dist/resources/account.d.ts +0 -18
  95. package/dist/resources/account.d.ts.map +0 -1
  96. package/dist/resources/definition-revisions.d.ts +0 -75
  97. package/dist/resources/definition-revisions.d.ts.map +0 -1
  98. package/dist/resources/definition-revisions.js +0 -142
  99. package/dist/resources/definitions.d.ts +0 -50
  100. package/dist/resources/definitions.d.ts.map +0 -1
  101. package/dist/resources/definitions.js +0 -73
  102. package/src/resources/definition-revisions.ts +0 -265
  103. package/src/resources/definitions.ts +0 -146
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typeship-ax/mcp",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "description": "MCP server for typeship.",
5
5
  "keywords": [
6
6
  "typeship",
package/server.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "url": "https://github.com/typeship-ax/mcp",
9
9
  "source": "github"
10
10
  },
11
- "version": "0.19.0",
11
+ "version": "0.21.0",
12
12
  "remotes": [
13
13
  {
14
14
  "type": "streamable-http",
@@ -24,7 +24,7 @@
24
24
  "registryType": "npm",
25
25
  "registryBaseUrl": "https://registry.npmjs.org",
26
26
  "identifier": "@typeship-ax/mcp",
27
- "version": "0.19.0",
27
+ "version": "0.21.0",
28
28
  "transport": {
29
29
  "type": "stdio"
30
30
  },
@@ -76,9 +76,13 @@ export function identityFetch(apiBaseUrl: string): typeof fetch {
76
76
 
77
77
  type IdentityResult = { ok: boolean; data?: unknown; error?: { status?: number } };
78
78
  export async function identityResult(client: unknown, operation: { resource: string; method: string }): Promise<IdentityResult> {
79
- const target = (client as Record<string, Record<string, () => Promise<IdentityResult>>>)[operation.resource];
79
+ const target = (client as Record<string, Record<string, () => Promise<unknown>>>)[operation.resource];
80
80
  if (!target?.[operation.method]) throw new Error("The configured identity operation is not available in this package.");
81
- return target[operation.method]!();
81
+ try {
82
+ return { ok: true, data: await target[operation.method]!() };
83
+ } catch (error) {
84
+ return { ok: false, error: error as { status?: number } };
85
+ }
82
86
  }
83
87
 
84
88
  export function verifyClientIdentity(createClient: (options: Record<string, unknown>) => unknown, options: Record<string, unknown>, operation: { resource: string; method: string }, policy: IdentityPolicy, expected?: ApiIdentity): Promise<VerifiedIdentity> {
package/src/core/http.ts CHANGED
@@ -19,7 +19,7 @@ export interface ResponseMeta {
19
19
  headers: Headers;
20
20
  /** Parsed wire body before it is narrowed to the generated response type.
21
21
  * Use this escape hatch for additive fields or variants introduced after
22
- * this generator edition. */
22
+ * this generator version. */
23
23
  rawBody?: unknown;
24
24
  /** Request identifier from the JSON response body, or from headers for
25
25
  * raw and bodyless responses. */
@@ -43,11 +43,7 @@ export interface RequestContext {
43
43
  }
44
44
 
45
45
 
46
- /**
47
- * Every SDK call returns a discriminated result instead of throwing.
48
- * Narrow on `ok` and the error side is a typed union of the documented
49
- * error responses for that exact operation.
50
- */
46
+ /** Internal result used by CLI and MCP consumers of the shared core. */
51
47
  export type ApiResult<T, E> =
52
48
  | { ok: true; data: T; response: ResponseMeta }
53
49
  | { ok: false; error: E; response?: ResponseMeta };
@@ -59,15 +55,80 @@ export function unwrap<T, E>(result: ApiResult<T, E>): T {
59
55
  throw new Error(String(result.error));
60
56
  }
61
57
 
58
+ /** Adapter for generated CLI and MCP entry points that consume result objects. */
59
+ export async function asApiResult<T>(call: PromiseLike<T>): Promise<{ ok: boolean; data?: T; error?: unknown; response?: ResponseMeta }> {
60
+ try {
61
+ const data = await call;
62
+ const pageResponse = data && typeof data === "object" && "response" in data
63
+ ? (data as { response?: ResponseMeta }).response : undefined;
64
+ const response = pageResponse ?? {
65
+ status: 0,
66
+ headers: new Headers(),
67
+ rawBody: data,
68
+ requestId: requestIdFromBody(data),
69
+ };
70
+ return { ok: true, data, response };
71
+ } catch (error) {
72
+ const response = error && typeof error === "object" && "response" in error
73
+ ? (error as { response?: ResponseMeta }).response : undefined;
74
+ return { ok: false, error, response };
75
+ }
76
+ }
77
+
78
+ /** Common fields on every failure. A missing response has status null. */
79
+ export class SdkError extends Error {
80
+ readonly code: string;
81
+ readonly status: number | null;
82
+ readonly requestId?: string;
83
+ readonly body: unknown;
84
+
85
+ constructor(message: string, code: string, status: number | null = null, body?: unknown, requestId?: string) {
86
+ super(message);
87
+ this.name = new.target.name;
88
+ this.code = code;
89
+ this.status = status;
90
+ this.body = body;
91
+ this.requestId = requestId;
92
+ }
93
+ }
94
+
95
+ function errorCode(body: unknown, fallback: string): string {
96
+ if (body && typeof body === "object" && !Array.isArray(body)) {
97
+ const value = body as Record<string, unknown>;
98
+ const first = Array.isArray(value.errors) ? value.errors[0] as { code?: unknown } | undefined : undefined;
99
+ const code = value.code ?? first?.code;
100
+ if (typeof code === "string" && code.trim()) return code;
101
+ }
102
+ return fallback;
103
+ }
104
+
105
+ function errorDetail(body: unknown): string {
106
+ if (!body || typeof body !== "object" || Array.isArray(body)) return "";
107
+ const value = body as Record<string, unknown>;
108
+ const first = Array.isArray(value.errors) ? value.errors[0] as { message?: unknown } | undefined : undefined;
109
+ const detail = value.message ?? value.error ?? value.detail ?? first?.message;
110
+ return typeof detail === "string" && detail.trim() ? ": " + detail : "";
111
+ }
112
+
113
+ function nextStep(status: number): string {
114
+ if (status === 401) return "Check the credential and retry.";
115
+ if (status === 403) return "Check the credential's permissions and retry.";
116
+ if (status === 404) return "Check the requested identifier or path.";
117
+ if (status === 409) return "Refresh the resource and retry the change.";
118
+ if (status === 422 || status === 400) return "Correct the request and retry.";
119
+ if (status === 429) return "Wait before retrying the request.";
120
+ if (status >= 500) return "Retry later; contact the API provider if this continues.";
121
+ return "Inspect the error body and correct the request before retrying.";
122
+ }
123
+
62
124
  /** Base class for every HTTP error response. */
63
- export class ApiError<S extends number = number, B = unknown> extends Error {
125
+ export class ApiError<S extends number = number, B = unknown> extends SdkError {
64
126
  readonly status: S;
65
127
  readonly body: B;
66
128
  readonly response: ResponseMeta;
67
129
 
68
130
  constructor(message: string, status: S, body: B, response: ResponseMeta) {
69
- super(message);
70
- this.name = new.target.name;
131
+ super(message + errorDetail(body) + ". " + nextStep(status), errorCode(body, "http_" + status), status, body, response.requestId);
71
132
  this.status = status;
72
133
  this.body = body;
73
134
  this.response = response;
@@ -82,15 +143,14 @@ export class UnexpectedApiError extends ApiError<number, unknown> {
82
143
  }
83
144
 
84
145
  /** A successful response declared JSON but carried a body that could not be parsed. */
85
- export class ResponseParseError extends Error {
146
+ export class ResponseParseError extends SdkError {
86
147
  readonly status: number;
87
148
  readonly body: string;
88
149
  readonly response: ResponseMeta;
89
150
  override readonly cause?: unknown;
90
151
 
91
152
  constructor(body: string, response: ResponseMeta, cause?: unknown) {
92
- super("HTTP " + response.status + " response body was not valid JSON");
93
- this.name = "ResponseParseError";
153
+ super("HTTP " + response.status + " response body was not valid JSON. Check the API response or contact its provider.", "response_parse_error", response.status, body, response.requestId);
94
154
  this.status = response.status;
95
155
  this.body = body;
96
156
  this.response = response;
@@ -105,18 +165,16 @@ export class ResponseParseError extends Error {
105
165
 
106
166
  export interface Violation { path: string; message: string }
107
167
 
108
- /** Request or response data did not match the spec's schema (opt-in via the
109
- * client's validate option). Never thrown: returned as the error side of
110
- * ApiResult, like every other failure. */
111
- export class ValidationError extends Error {
168
+ /** Request or response data did not match the spec's schema. */
169
+ export class ValidationError extends SdkError {
112
170
  readonly direction: "request" | "response";
113
171
  readonly target: "body" | "parameters";
114
172
  readonly violations: Violation[];
115
173
  constructor(direction: "request" | "response", violations: Violation[], target: "body" | "parameters" = "body") {
116
174
  const shown = violations.slice(0, 3).map((v) => v.path + " " + v.message).join("; ");
117
175
  super(direction + " " + target + " failed schema validation: " + shown
118
- + (violations.length > 3 ? " (+" + (violations.length - 3) + " more)" : ""));
119
- this.name = "ValidationError";
176
+ + (violations.length > 3 ? " (+" + (violations.length - 3) + " more)" : "")
177
+ + ". Correct the " + (direction === "request" ? "request" : "API response or update the spec") + ".", "validation_error");
120
178
  this.direction = direction;
121
179
  this.target = target;
122
180
  this.violations = violations;
@@ -251,13 +309,14 @@ function transportFailureMessage(method: string, url: string, cause: unknown): s
251
309
  }
252
310
 
253
311
  /** The request failed before a complete HTTP response arrived (network failure, timeout, abort, or truncated body). */
254
- export class TransportError extends Error {
312
+ export class TransportError extends SdkError {
255
313
  override readonly cause?: unknown;
314
+ readonly response?: ResponseMeta;
256
315
 
257
- constructor(message: string, cause?: unknown) {
258
- super(message);
259
- this.name = "TransportError";
316
+ constructor(message: string, cause?: unknown, response?: ResponseMeta) {
317
+ super(message + ". Check the connection and retry.", "transport_error", response?.status ?? null, undefined, response?.requestId);
260
318
  this.cause = cause;
319
+ this.response = response;
261
320
  }
262
321
  }
263
322
 
@@ -521,6 +580,7 @@ export class HttpCore {
521
580
  const error = (parseError ?? new TransportError(
522
581
  "The response body read failed before completing",
523
582
  cause,
583
+ meta(response),
524
584
  )) as unknown as E;
525
585
  await this.config.onError?.(error, { method: req.method, path: req.path });
526
586
  return { ok: false, error, response: parseError?.response ?? meta(response) };
@@ -567,8 +627,8 @@ export class HttpCore {
567
627
  let body: unknown;
568
628
  try {
569
629
  body = await parseBody(response, req.method);
570
- } catch {
571
- body = undefined; // error responses keep their status even if the body read aborts
630
+ } catch (cause) {
631
+ body = cause instanceof ResponseParseError ? cause.body : undefined;
572
632
  }
573
633
  emitResponseDebug(response, body);
574
634
  const responseMeta = meta(response, body);
@@ -589,6 +649,11 @@ export class HttpCore {
589
649
  return { ok: false, error };
590
650
  }
591
651
 
652
+ /** SDK-facing call: resolve to the payload or throw its typed error. */
653
+ async requestData<T, E>(req: CoreRequest): Promise<T> {
654
+ return unwrap(await this.request<T, E>(req));
655
+ }
656
+
592
657
  private async send(
593
658
  req: CoreRequest,
594
659
  timeoutMs: number,
@@ -1,13 +1,12 @@
1
1
  /**
2
2
  * Auto-pagination. Generated by typeship — https://typeship.dev
3
3
  *
4
- * List operations return a PagePromise: `await` it for one page (a typed
5
- * ApiResult), or `for await` it to stream every item across every page.
4
+ * List operations return a PagePromise: `await` it for one page, or
5
+ * `for await` it to stream every item across every page.
6
6
  */
7
7
 
8
8
  import {
9
9
  HttpCore,
10
- type ApiResult,
11
10
  type CoreRequest,
12
11
  type ResponseMeta,
13
12
  } from "./http.js";
@@ -29,7 +28,7 @@ export interface PageConfig {
29
28
 
30
29
  type FetchPage<Item, E> = (
31
30
  query: Record<string, unknown>,
32
- ) => Promise<ApiResult<Page<Item, E>, E>>;
31
+ ) => Promise<Page<Item, E>>;
33
32
 
34
33
  export class Page<Item, E = unknown> {
35
34
  private readonly fetchPage: FetchPage<Item, E>;
@@ -85,11 +84,7 @@ export class Page<Item, E = unknown> {
85
84
  async getNextPage(): Promise<Page<Item, E> | null> {
86
85
  const next = this.nextPageParams();
87
86
  if (next === null) return null;
88
- const result = await this.fetchPage(next);
89
- if (!result.ok) {
90
- throw result.error instanceof Error ? result.error : new Error(String(result.error));
91
- }
92
- return result.data;
87
+ return this.fetchPage(next);
93
88
  }
94
89
 
95
90
  /** Iterate every item on this page and all following pages. */
@@ -114,28 +109,24 @@ export class Page<Item, E = unknown> {
114
109
  }
115
110
 
116
111
  /**
117
- * Awaitable (one page, as a typed ApiResult) and async-iterable (all items,
112
+ * Awaitable (one page) and async-iterable (all items,
118
113
  * all pages). Iteration throws the operation's typed error union on failure.
119
114
  */
120
- export class PagePromise<Item, E> implements PromiseLike<ApiResult<Page<Item, E>, E>>, AsyncIterable<Item> {
121
- private readonly first: Promise<ApiResult<Page<Item, E>, E>>;
122
- constructor(first: Promise<ApiResult<Page<Item, E>, E>>) {
115
+ export class PagePromise<Item, E> implements PromiseLike<Page<Item, E>>, AsyncIterable<Item> {
116
+ private readonly first: Promise<Page<Item, E>>;
117
+ constructor(first: Promise<Page<Item, E>>) {
123
118
  this.first = first;
124
119
  }
125
120
 
126
- then<R1 = ApiResult<Page<Item, E>, E>, R2 = never>(
127
- onfulfilled?: ((value: ApiResult<Page<Item, E>, E>) => R1 | PromiseLike<R1>) | null,
121
+ then<R1 = Page<Item, E>, R2 = never>(
122
+ onfulfilled?: ((value: Page<Item, E>) => R1 | PromiseLike<R1>) | null,
128
123
  onrejected?: ((reason: unknown) => R2 | PromiseLike<R2>) | null,
129
124
  ): Promise<R1 | R2> {
130
125
  return this.first.then(onfulfilled, onrejected);
131
126
  }
132
127
 
133
128
  async *[Symbol.asyncIterator](): AsyncIterator<Item, void, undefined> {
134
- const result = await this.first;
135
- if (!result.ok) {
136
- throw result.error instanceof Error ? result.error : new Error(String(result.error));
137
- }
138
- yield* result.data;
129
+ yield* await this.first;
139
130
  }
140
131
  }
141
132
 
@@ -149,9 +140,8 @@ export function paginate<Item, E>(
149
140
  const fetchPage: FetchPage<Item, E> = async (params) => {
150
141
  let nextReq: CoreRequest = { ...req, query: params };
151
142
  const result = await core.request<unknown, E>(nextReq);
152
- if (!result.ok) return result;
153
- const page = new Page<Item, E>(fetchPage, config, params, result.data, result.response);
154
- return { ok: true, data: page, response: result.response };
143
+ if (!result.ok) throw result.error instanceof Error ? result.error : new Error(String(result.error));
144
+ return new Page<Item, E>(fetchPage, config, params, result.data, result.response);
155
145
  };
156
146
  const initial: Record<string, unknown> = {};
157
147
  let seed = req.query ?? {};
package/src/errors.ts CHANGED
@@ -4,15 +4,15 @@
4
4
  import { ApiError, type ResponseMeta } from "./core/http.js";
5
5
  import type { ErrorModel, ErrorModelRead } from "./types.js";
6
6
 
7
- export { ApiError, ResponseParseError, TransportError, UnexpectedApiError, ValidationError, type Violation, unwrap } from "./core/http.js";
7
+ export { ApiError, SdkError, ResponseParseError, TransportError, UnexpectedApiError, ValidationError, type Violation } from "./core/http.js";
8
8
 
9
9
  /**
10
- * The request body, Definition source, target selection, or package name is invalid.
10
+ * The request body, Spec source, target selection, or package name is invalid.
11
11
  * Raised for HTTP 400 responses.
12
12
  */
13
13
  export class BadRequestError extends ApiError<400, ErrorModelRead> {
14
14
  constructor(body: ErrorModelRead, response: ResponseMeta) {
15
- super("The request body, Definition source, target selection, or package name is invalid.", 400, body, response);
15
+ super("The request body, Spec source, target selection, or package name is invalid.", 400, body, response);
16
16
  }
17
17
  }
18
18
 
@@ -57,12 +57,12 @@ export class PayloadTooLargeError extends ApiError<413, ErrorModelRead> {
57
57
  }
58
58
 
59
59
  /**
60
- * The Definition could not be resolved or understood.
60
+ * The Spec could not be resolved or understood.
61
61
  * Raised for HTTP 422 responses.
62
62
  */
63
63
  export class UnprocessableEntityError extends ApiError<422, ErrorModelRead> {
64
64
  constructor(body: ErrorModelRead, response: ResponseMeta) {
65
- super("The Definition could not be resolved or understood.", 422, body, response);
65
+ super("The Spec could not be resolved or understood.", 422, body, response);
66
66
  }
67
67
  }
68
68
 
@@ -98,12 +98,12 @@ export class ApiResponseError extends ApiError<number, ErrorModelRead> {
98
98
  }
99
99
 
100
100
  /**
101
- * No such resource in this account.
101
+ * No such resource in this organization.
102
102
  * Raised for HTTP 404 responses.
103
103
  */
104
104
  export class NotFoundError extends ApiError<404, ErrorModelRead> {
105
105
  constructor(body: ErrorModelRead, response: ResponseMeta) {
106
- super("No such resource in this account.", 404, body, response);
106
+ super("No such resource in this organization.", 404, body, response);
107
107
  }
108
108
  }
109
109
 
package/src/index.ts CHANGED
@@ -14,16 +14,21 @@ import { DEFS, SCHEMAS } from "./schemas.js";
14
14
 
15
15
  import { GenerateResource } from "./resources/generate.js";
16
16
  import { ProjectsResource } from "./resources/projects.js";
17
- import { DefinitionsResource } from "./resources/definitions.js";
17
+ import { SpecsResource } from "./resources/specs.js";
18
+ import { SpecRevisionsResource } from "./resources/spec-revisions.js";
18
19
  import { TargetsResource } from "./resources/targets.js";
20
+ import { DraftsResource } from "./resources/drafts.js";
21
+ import { ReleasesResource } from "./resources/releases.js";
22
+ import { DeliveriesResource } from "./resources/deliveries.js";
23
+ import { PublicationsResource } from "./resources/publications.js";
19
24
  import { GenerationsResource } from "./resources/generations.js";
20
- import { DefinitionRevisionsResource } from "./resources/definition-revisions.js";
21
- import { AccountResource } from "./resources/account.js";
25
+ import { FilesResource } from "./resources/files.js";
26
+ import { OrganizationResource } from "./resources/organization.js";
22
27
  import { ApiKeysResource } from "./resources/api-keys.js";
23
28
 
24
29
  /** This package's version, also sent as the `User-Agent`. */
25
- export const VERSION = "0.19.0";
26
- const USER_AGENT = "@typeship-ax/mcp/0.19.0";
30
+ export const VERSION = "0.21.0";
31
+ const USER_AGENT = "@typeship-ax/mcp/0.21.0";
27
32
 
28
33
  export interface ClientOptions {
29
34
  /** Override the server URL. Default: `https://typeship.dev/api/v1` */
@@ -34,8 +39,8 @@ export interface ClientOptions {
34
39
  */
35
40
  bearerToken?: string | (() => string | Promise<string>);
36
41
  /**
37
- * Credentials keyed by the Definition's security scheme names. Only one complete alternative is
38
- * sent for each operation. Named values take precedence over convenience options.
42
+ * Credentials keyed by the Spec's security scheme names. Only one complete alternative is sent
43
+ * for each operation. Named values take precedence over convenience options.
39
44
  */
40
45
  credentials?: {
41
46
  "apiKey"?: AuthValue;
@@ -71,17 +76,16 @@ export interface ClientOptions {
71
76
  debug?: boolean | ((event: DebugEvent) => void);
72
77
  /**
73
78
  * Opt-in zero-dependency runtime validation of JSON bodies against the spec's schemas: true
74
- * checks requests and responses and returns a ValidationError on mismatch (as the ApiResult
75
- * error, never thrown); mode "warn" logs via console.warn and lets the call proceed. Catches spec
76
- * drift the type system can't see.
79
+ * checks requests and responses and throws ValidationError on mismatch; mode "warn" logs via
80
+ * console.warn and lets the call proceed. Catches spec drift the type system can't see.
77
81
  */
78
82
  validate?: boolean | { requests?: boolean; responses?: boolean; mode?: "throw" | "warn" };
79
83
  }
80
84
 
81
85
  /**
82
- * typeship — v0.19.0
86
+ * typeship — v0.21.0
83
87
  *
84
- * Resolve an OpenAPI or GraphQL Definition, diagnose it, and keep every
88
+ * Resolve an OpenAPI or GraphQL Spec, diagnose it, and keep every
85
89
  * selected CLI, MCP, and SDK Target current.
86
90
  *
87
91
  * Every operation but one requires a bearer credential: an organization
@@ -93,16 +97,21 @@ export interface ClientOptions {
93
97
  *
94
98
  * Examples use Parcel, a fictional delivery service. Replace its domains,
95
99
  * repository names, and resource identifiers with your own. The hosted
96
- * petstore Definition is a runnable sample.
100
+ * petstore Spec is a runnable sample.
97
101
  */
98
102
  export class TypeshipClient {
99
103
  readonly generate: GenerateResource;
100
104
  readonly projects: ProjectsResource;
101
- readonly definitions: DefinitionsResource;
105
+ readonly specs: SpecsResource;
106
+ readonly specRevisions: SpecRevisionsResource;
102
107
  readonly targets: TargetsResource;
108
+ readonly drafts: DraftsResource;
109
+ readonly releases: ReleasesResource;
110
+ readonly deliveries: DeliveriesResource;
111
+ readonly publications: PublicationsResource;
103
112
  readonly generations: GenerationsResource;
104
- readonly definitionRevisions: DefinitionRevisionsResource;
105
- readonly account: AccountResource;
113
+ readonly files: FilesResource;
114
+ readonly organization: OrganizationResource;
106
115
  readonly apiKeys: ApiKeysResource;
107
116
 
108
117
  constructor(options: ClientOptions = {}) {
@@ -160,11 +169,16 @@ export class TypeshipClient {
160
169
  });
161
170
  this.generate = new GenerateResource(core);
162
171
  this.projects = new ProjectsResource(core);
163
- this.definitions = new DefinitionsResource(core);
172
+ this.specs = new SpecsResource(core);
173
+ this.specRevisions = new SpecRevisionsResource(core);
164
174
  this.targets = new TargetsResource(core);
175
+ this.drafts = new DraftsResource(core);
176
+ this.releases = new ReleasesResource(core);
177
+ this.deliveries = new DeliveriesResource(core);
178
+ this.publications = new PublicationsResource(core);
165
179
  this.generations = new GenerationsResource(core);
166
- this.definitionRevisions = new DefinitionRevisionsResource(core);
167
- this.account = new AccountResource(core);
180
+ this.files = new FilesResource(core);
181
+ this.organization = new OrganizationResource(core);
168
182
  this.apiKeys = new ApiKeysResource(core);
169
183
  }
170
184
  }
@@ -173,7 +187,6 @@ export * from "./types.js";
173
187
  export * from "./errors.js";
174
188
  export {
175
189
  formatDebugEvent,
176
- type ApiResult,
177
190
  type AuthValue,
178
191
  type DebugEvent,
179
192
  type RequestContext,
@@ -184,9 +197,14 @@ export { Page, PagePromise } from "./core/pagination.js";
184
197
 
185
198
  export * from "./resources/generate.js";
186
199
  export * from "./resources/projects.js";
187
- export * from "./resources/definitions.js";
200
+ export * from "./resources/specs.js";
201
+ export * from "./resources/spec-revisions.js";
188
202
  export * from "./resources/targets.js";
203
+ export * from "./resources/drafts.js";
204
+ export * from "./resources/releases.js";
205
+ export * from "./resources/deliveries.js";
206
+ export * from "./resources/publications.js";
189
207
  export * from "./resources/generations.js";
190
- export * from "./resources/definition-revisions.js";
191
- export * from "./resources/account.js";
208
+ export * from "./resources/files.js";
209
+ export * from "./resources/organization.js";
192
210
  export * from "./resources/api-keys.js";
@@ -1618,8 +1618,8 @@ function omittedPlanLimit(ops: OpLike[], requested?: string): ToolOutcome {
1618
1618
  error: "PlanLimitError",
1619
1619
  code: "PLAN_LIMIT",
1620
1620
  message: requested
1621
- ? "The operation " + requested + " exists in the API Definition but was omitted from this generated package by its plan limit."
1622
- : "Matching operations exist in the API Definition but were omitted from this generated package by its plan limit.",
1621
+ ? "The operation " + requested + " exists in the Spec but was omitted from this generated package by its plan limit."
1622
+ : "Matching operations exist in the Spec but were omitted from this generated package by its plan limit.",
1623
1623
  omitted_operations: ops.map((op) => ({ tool: op.tool, method: op.httpMethod, path: op.path })),
1624
1624
  next_steps: ["Upgrade at https://typeship.dev/pricing and regenerate the package without the operation cap.", "Do not invent or retry an omitted operation against this generated package."],
1625
1625
  };
package/src/mcp.ts CHANGED
@@ -22,6 +22,7 @@ import { homedir, tmpdir } from "node:os";
22
22
  import { basename, join } from "node:path";
23
23
  import { fileURLToPath } from "node:url";
24
24
  import { TypeshipClient, formatDebugEvent, type ClientOptions, type DebugEvent } from "./index.js";
25
+ import { asApiResult } from "./core/http.js";
25
26
  import { GLOBALS, OMITTED_OPS, OPS, buildArgs, type OpSpec } from "./ops.js";
26
27
  import {
27
28
  DEFAULT_MAX_RESULT_CHARS, SUPPORTED_PROTOCOL_VERSIONS, McpAccountLinkRequired, argumentsError, asJsonRpc, binaryOutcome, callSharedTool, checkRequestHeaders,
@@ -42,7 +43,7 @@ export { McpAccountLinkRequired } from "./mcp-protocol.js";
42
43
  const BIN = "typeship";
43
44
  const PKG_NAME = "@typeship-ax/mcp";
44
45
  const SERVER_NAME = "typeship-mcp";
45
- const SERVER_VERSION = "0.19.0";
46
+ const SERVER_VERSION = "0.21.0";
46
47
  /** The MCP client's announced name (clientInfo in request _meta), for the User-Agent. */
47
48
  let MCP_CLIENT_NAME: string | null = null;
48
49
  function noteClientInfo(message: unknown): void {
@@ -64,7 +65,7 @@ const TOOL_MODE: "operations" | "meta" = "meta";
64
65
  /** Project-supplied guidance appended to the server instructions. */
65
66
  const CUSTOM_INSTRUCTIONS: string | null = null;
66
67
  /** The tool that returns the caller (the CLI's whoami target), named in the instructions. */
67
- const IDENTITY_TOOL: string | null = "account_retrieve";
68
+ const IDENTITY_TOOL: string | null = null;
68
69
  /** Surface switches: reads only, and/or a subset of resources or tools.
69
70
  * Flags win over the environment. */
70
71
  const ARGV = process.argv.slice(2);
@@ -207,14 +208,14 @@ async function callOperationRaw(op: OpSpec, rawArgs: Record<string, unknown>, re
207
208
  const shape = { fields, maxChars, pagination: op.pagination, args };
208
209
  try {
209
210
  const target = (client as unknown as Record<string, Record<string, (...a: unknown[]) => unknown>>)[op.resource]!;
210
- let result = await (target[op.method]!(...callArgs) as Promise<{ ok: boolean; data?: unknown; error?: unknown; response?: { requestId?: string } }>);
211
+ let result = await asApiResult(target[op.method]!(...callArgs) as Promise<unknown>);
211
212
  if (!result.ok) return errorOutcome(result.error, errorContext);
212
- if (op.httpMethod === "POST" && op.path === "/projects/{project_id}/generations") {
213
+ if (op.httpMethod === "POST" && op.path === "/projects/{project_id}/generate") {
213
214
  const batch = result.data as { data: Array<{ id: string }> };
214
- const generations = (client as unknown as { generations: { wait(id: string): Promise<{ ok: boolean; data?: unknown; error?: unknown }> } }).generations;
215
+ const generations = (client as unknown as { generations: { wait(id: string): Promise<unknown> } }).generations;
215
216
  const completed: unknown[] = [];
216
217
  for (const generation of batch.data) {
217
- const waited = await generations.wait(generation.id);
218
+ const waited = await asApiResult(generations.wait(generation.id));
218
219
  if (!waited.ok) return errorOutcome(waited.error, errorContext);
219
220
  completed.push(waited.data);
220
221
  }