@voyant-travel/trips 0.110.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.
Files changed (63) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +38 -0
  3. package/dist/catalog-component-adapter.d.ts +16 -0
  4. package/dist/catalog-component-adapter.d.ts.map +1 -0
  5. package/dist/catalog-component-adapter.js +34 -0
  6. package/dist/cruise-extension.d.ts +48 -0
  7. package/dist/cruise-extension.d.ts.map +1 -0
  8. package/dist/cruise-extension.js +66 -0
  9. package/dist/index.d.ts +24 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +31 -0
  12. package/dist/mcp-contract.d.ts +79 -0
  13. package/dist/mcp-contract.d.ts.map +1 -0
  14. package/dist/mcp-contract.js +21 -0
  15. package/dist/mcp-registry.d.ts +48 -0
  16. package/dist/mcp-registry.d.ts.map +1 -0
  17. package/dist/mcp-registry.js +88 -0
  18. package/dist/mcp-tools.d.ts +157 -0
  19. package/dist/mcp-tools.d.ts.map +1 -0
  20. package/dist/mcp-tools.js +109 -0
  21. package/dist/routes.d.ts +2068 -0
  22. package/dist/routes.d.ts.map +1 -0
  23. package/dist/routes.js +280 -0
  24. package/dist/schema.d.ts +1897 -0
  25. package/dist/schema.d.ts.map +1 -0
  26. package/dist/schema.js +255 -0
  27. package/dist/service-cancellation.d.ts +6 -0
  28. package/dist/service-cancellation.d.ts.map +1 -0
  29. package/dist/service-cancellation.js +251 -0
  30. package/dist/service-checkout.d.ts +6 -0
  31. package/dist/service-checkout.d.ts.map +1 -0
  32. package/dist/service-checkout.js +328 -0
  33. package/dist/service-helpers.d.ts +17 -0
  34. package/dist/service-helpers.d.ts.map +1 -0
  35. package/dist/service-helpers.js +161 -0
  36. package/dist/service-internals.d.ts +11 -0
  37. package/dist/service-internals.d.ts.map +1 -0
  38. package/dist/service-internals.js +72 -0
  39. package/dist/service-pricing.d.ts +8 -0
  40. package/dist/service-pricing.d.ts.map +1 -0
  41. package/dist/service-pricing.js +142 -0
  42. package/dist/service-reservation.d.ts +5 -0
  43. package/dist/service-reservation.d.ts.map +1 -0
  44. package/dist/service-reservation.js +493 -0
  45. package/dist/service-snapshots.d.ts +8 -0
  46. package/dist/service-snapshots.d.ts.map +1 -0
  47. package/dist/service-snapshots.js +115 -0
  48. package/dist/service-trips.d.ts +14 -0
  49. package/dist/service-trips.d.ts.map +1 -0
  50. package/dist/service-trips.js +378 -0
  51. package/dist/service-types.d.ts +285 -0
  52. package/dist/service-types.d.ts.map +1 -0
  53. package/dist/service-types.js +6 -0
  54. package/dist/service.d.ts +38 -0
  55. package/dist/service.d.ts.map +1 -0
  56. package/dist/service.js +40 -0
  57. package/dist/traveler-party-validation.d.ts +3 -0
  58. package/dist/traveler-party-validation.d.ts.map +1 -0
  59. package/dist/traveler-party-validation.js +68 -0
  60. package/dist/validation.d.ts +449 -0
  61. package/dist/validation.d.ts.map +1 -0
  62. package/dist/validation.js +261 -0
  63. package/package.json +83 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-registry.d.ts","sourceRoot":"","sources":["../src/mcp-registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGzF,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;IAChC,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,IAAI,CAAA;IACpE,2EAA2E;IAC3E,IAAI,IAAI,gBAAgB,EAAE,CAAA;IAC1B,+EAA+E;IAC/E,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACjE,wEAAwE;IAExE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC,GAAG,EAAE,aAAa,CAAC,GAAG,SAAS,CAAA;CACrE;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,kBAAkB,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5D;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,cAAc,CAAA;CACxB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,eAAe,CAuD5F;AAUD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CASzE;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,EAC9B,kBAAkB,CAAC,EAAE,MAAM,EAAE,GAC5B,IAAI,CASN;AAID,YAAY,EAAE,CAAC,EAAE,CAAA"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Transport-agnostic registry for trips agent tools.
3
+ */
4
+ import { McpToolError } from "./mcp-contract.js";
5
+ export function createMcpToolRegistry(options) {
6
+ // biome-ignore lint/suspicious/noExplicitAny: heterogeneous tool args -- owner: trips; existing suppression is intentional pending typed cleanup.
7
+ const tools = new Map();
8
+ return {
9
+ get context() {
10
+ return options.context;
11
+ },
12
+ register(tool) {
13
+ if (tools.has(tool.name)) {
14
+ throw new Error(`MCP tool "${tool.name}" is already registered`);
15
+ }
16
+ tools.set(tool.name, tool);
17
+ },
18
+ list() {
19
+ return Array.from(tools.values()).map((tool) => ({
20
+ name: tool.name,
21
+ description: tool.description,
22
+ inputSchemaPreview: {
23
+ type: "object",
24
+ description: "Use the package's zod-to-json-schema adapter to serialize for the MCP SDK.",
25
+ },
26
+ }));
27
+ },
28
+ get(name) {
29
+ return tools.get(name);
30
+ },
31
+ async dispatchTool(name, args) {
32
+ const tool = tools.get(name);
33
+ if (!tool) {
34
+ return errorResult(`MCP tool "${name}" is not registered. Known tools: ${Array.from(tools.keys()).join(", ") || "(none)"}`, "NOT_FOUND");
35
+ }
36
+ let parsed;
37
+ try {
38
+ parsed = tool.inputSchema.parse(args);
39
+ }
40
+ catch (err) {
41
+ const message = err instanceof Error ? err.message : String(err);
42
+ return errorResult(`Invalid input for tool "${name}": ${message}`, "INVALID_INPUT");
43
+ }
44
+ try {
45
+ return await tool.handler(parsed, options.context);
46
+ }
47
+ catch (err) {
48
+ if (err instanceof McpToolError) {
49
+ return errorResult(err.message, err.code, err.meta);
50
+ }
51
+ const message = err instanceof Error ? err.message : String(err);
52
+ return errorResult(`Tool "${name}" failed: ${message}`, "PROVIDER_ERROR");
53
+ }
54
+ },
55
+ };
56
+ }
57
+ function errorResult(message, code, meta) {
58
+ return {
59
+ isError: true,
60
+ content: [{ type: "text", text: `[${code}] ${message}` }],
61
+ structuredContent: { error: { code, message, ...(meta ?? {}) } },
62
+ };
63
+ }
64
+ /**
65
+ * Helper for tools to assert that a required service was injected
66
+ * into the context. Throws `MISSING_SERVICE` if not, which the dispatcher
67
+ * translates into a structured error.
68
+ */
69
+ export function requireService(service, name) {
70
+ if (!service) {
71
+ throw new McpToolError(`MCP tool requires the "${name}" service to be wired into the context, but it was not provided. Configure the registry services or omit tools that depend on it.`, "MISSING_SERVICE", { service: name });
72
+ }
73
+ return service;
74
+ }
75
+ /**
76
+ * Helper for tools that need to enforce per-actor authorization. Customer/
77
+ * partner/supplier actors are pinned to their own audience pool — staff
78
+ * actors may federate across pools.
79
+ */
80
+ export function enforceAudienceAuthorization(actor, requestedAudiences) {
81
+ if (!requestedAudiences || requestedAudiences.length === 0)
82
+ return;
83
+ if (actor === "staff")
84
+ return;
85
+ if (requestedAudiences.length === 1 && requestedAudiences[0] === actor)
86
+ return;
87
+ throw new McpToolError(`Actor "${actor}" is not authorized to query audiences ${JSON.stringify(requestedAudiences)}. Non-staff actors may only query their own audience pool.`, "AUTHORIZATION_DENIED", { actor, requestedAudiences });
88
+ }
@@ -0,0 +1,157 @@
1
+ import { z } from "zod";
2
+ import type { McpToolDefinition, McpToolResult } from "./mcp-contract.js";
3
+ import type { TripComponent } from "./schema.js";
4
+ import type { PriceTripResult, ReserveTripResult, Trip } from "./service.js";
5
+ import { type createTripComponentSchema, createTripEnvelopeSchema, priceTripSchema, reserveTripSchema } from "./validation.js";
6
+ export interface TripsMcpServices {
7
+ createTrip(input: z.infer<typeof createTripEnvelopeSchema>): Promise<Trip>;
8
+ addComponent(input: z.infer<typeof createTripComponentSchema>): Promise<TripComponent>;
9
+ removeComponent?(componentId: string): Promise<TripComponent | null>;
10
+ priceTrip(input: z.infer<typeof priceTripSchema>): Promise<PriceTripResult>;
11
+ reserveTrip(input: z.infer<typeof reserveTripSchema>): Promise<ReserveTripResult>;
12
+ }
13
+ declare const createTripArgs: z.ZodObject<{
14
+ title: z.ZodOptional<z.ZodString>;
15
+ description: z.ZodOptional<z.ZodString>;
16
+ travelerParty: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
17
+ constraints: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
18
+ createdBy: z.ZodOptional<z.ZodString>;
19
+ components: z.ZodDefault<z.ZodArray<z.ZodObject<{
20
+ description: z.ZodOptional<z.ZodString>;
21
+ sequence: z.ZodDefault<z.ZodNumber>;
22
+ kind: z.ZodEnum<{
23
+ catalog_booking: "catalog_booking";
24
+ manual_placeholder: "manual_placeholder";
25
+ flight_placeholder: "flight_placeholder";
26
+ flight_order: "flight_order";
27
+ external_order: "external_order";
28
+ }>;
29
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
30
+ catalogRef: z.ZodOptional<z.ZodObject<{
31
+ entityModule: z.ZodString;
32
+ entityId: z.ZodString;
33
+ sourceKind: z.ZodString;
34
+ sourceConnectionId: z.ZodOptional<z.ZodString>;
35
+ sourceRef: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strip>>;
37
+ estimatedPricing: z.ZodOptional<z.ZodObject<{
38
+ currency: z.ZodString;
39
+ subtotalAmountCents: z.ZodNumber;
40
+ taxAmountCents: z.ZodNumber;
41
+ totalAmountCents: z.ZodNumber;
42
+ priceExpiresAt: z.ZodOptional<z.ZodString>;
43
+ warnings: z.ZodOptional<z.ZodArray<z.ZodString>>;
44
+ }, z.core.$strip>>;
45
+ }, z.core.$strict>>>;
46
+ }, z.core.$strip>;
47
+ export type CreateTripArgs = z.infer<typeof createTripArgs>;
48
+ export declare const createTripTool: McpToolDefinition<CreateTripArgs, McpToolResult>;
49
+ declare const reviseTripArgs: z.ZodObject<{
50
+ envelopeId: z.ZodString;
51
+ addComponents: z.ZodDefault<z.ZodArray<z.ZodObject<{
52
+ description: z.ZodOptional<z.ZodString>;
53
+ sequence: z.ZodDefault<z.ZodNumber>;
54
+ kind: z.ZodEnum<{
55
+ catalog_booking: "catalog_booking";
56
+ manual_placeholder: "manual_placeholder";
57
+ flight_placeholder: "flight_placeholder";
58
+ flight_order: "flight_order";
59
+ external_order: "external_order";
60
+ }>;
61
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
62
+ catalogRef: z.ZodOptional<z.ZodObject<{
63
+ entityModule: z.ZodString;
64
+ entityId: z.ZodString;
65
+ sourceKind: z.ZodString;
66
+ sourceConnectionId: z.ZodOptional<z.ZodString>;
67
+ sourceRef: z.ZodOptional<z.ZodString>;
68
+ }, z.core.$strip>>;
69
+ estimatedPricing: z.ZodOptional<z.ZodObject<{
70
+ currency: z.ZodString;
71
+ subtotalAmountCents: z.ZodNumber;
72
+ taxAmountCents: z.ZodNumber;
73
+ totalAmountCents: z.ZodNumber;
74
+ priceExpiresAt: z.ZodOptional<z.ZodString>;
75
+ warnings: z.ZodOptional<z.ZodArray<z.ZodString>>;
76
+ }, z.core.$strip>>;
77
+ }, z.core.$strict>>>;
78
+ removeComponentIds: z.ZodDefault<z.ZodArray<z.ZodString>>;
79
+ }, z.core.$strip>;
80
+ export type ReviseTripArgs = z.infer<typeof reviseTripArgs>;
81
+ export declare const reviseTripTool: McpToolDefinition<ReviseTripArgs, McpToolResult>;
82
+ export type PriceTripArgs = z.infer<typeof priceTripSchema>;
83
+ export declare const priceTripTool: McpToolDefinition<PriceTripArgs, McpToolResult>;
84
+ export type ReserveTripArgs = z.infer<typeof reserveTripSchema>;
85
+ export declare const reserveTripTool: McpToolDefinition<ReserveTripArgs, McpToolResult>;
86
+ export declare const tripsMcpTools: readonly [McpToolDefinition<{
87
+ travelerParty: Record<string, unknown>;
88
+ constraints: Record<string, unknown>;
89
+ components: {
90
+ sequence: number;
91
+ kind: "catalog_booking" | "manual_placeholder" | "flight_placeholder" | "flight_order" | "external_order";
92
+ metadata: Record<string, unknown>;
93
+ description?: string | undefined;
94
+ catalogRef?: {
95
+ entityModule: string;
96
+ entityId: string;
97
+ sourceKind: string;
98
+ sourceConnectionId?: string | undefined;
99
+ sourceRef?: string | undefined;
100
+ } | undefined;
101
+ estimatedPricing?: {
102
+ currency: string;
103
+ subtotalAmountCents: number;
104
+ taxAmountCents: number;
105
+ totalAmountCents: number;
106
+ priceExpiresAt?: string | undefined;
107
+ warnings?: string[] | undefined;
108
+ } | undefined;
109
+ }[];
110
+ title?: string | undefined;
111
+ description?: string | undefined;
112
+ createdBy?: string | undefined;
113
+ }, McpToolResult>, McpToolDefinition<{
114
+ envelopeId: string;
115
+ addComponents: {
116
+ sequence: number;
117
+ kind: "catalog_booking" | "manual_placeholder" | "flight_placeholder" | "flight_order" | "external_order";
118
+ metadata: Record<string, unknown>;
119
+ description?: string | undefined;
120
+ catalogRef?: {
121
+ entityModule: string;
122
+ entityId: string;
123
+ sourceKind: string;
124
+ sourceConnectionId?: string | undefined;
125
+ sourceRef?: string | undefined;
126
+ } | undefined;
127
+ estimatedPricing?: {
128
+ currency: string;
129
+ subtotalAmountCents: number;
130
+ taxAmountCents: number;
131
+ totalAmountCents: number;
132
+ priceExpiresAt?: string | undefined;
133
+ warnings?: string[] | undefined;
134
+ } | undefined;
135
+ }[];
136
+ removeComponentIds: string[];
137
+ }, McpToolResult>, McpToolDefinition<{
138
+ envelopeId: string;
139
+ scope: {
140
+ locale: string;
141
+ audience: "staff" | "customer" | "partner" | "supplier";
142
+ market: string;
143
+ currency?: string | undefined;
144
+ };
145
+ ttlMs?: number | undefined;
146
+ }, McpToolResult>, McpToolDefinition<{
147
+ envelopeId: string;
148
+ idempotencyKey?: string | undefined;
149
+ refreshScope?: {
150
+ locale: string;
151
+ audience: "staff" | "customer" | "partner" | "supplier";
152
+ market: string;
153
+ currency?: string | undefined;
154
+ } | undefined;
155
+ }, McpToolResult>];
156
+ export {};
157
+ //# sourceMappingURL=mcp-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.d.ts","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAkB,iBAAiB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC5E,OAAO,EAEL,KAAK,yBAAyB,EAC9B,wBAAwB,EACxB,eAAe,EACf,iBAAiB,EAClB,MAAM,iBAAiB,CAAA;AAExB,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1E,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACtF,eAAe,CAAC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;IACpE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC3E,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;CAClF;AAMD,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAElB,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAE3D,eAAO,MAAM,cAAc,EAAE,iBAAiB,CAAC,cAAc,EAAE,aAAa,CAgC3E,CAAA;AAED,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIlB,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAE3D,eAAO,MAAM,cAAc,EAAE,iBAAiB,CAAC,cAAc,EAAE,aAAa,CAmC3E,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAE3D,eAAO,MAAM,aAAa,EAAE,iBAAiB,CAAC,aAAa,EAAE,aAAa,CAYzE,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE/D,eAAO,MAAM,eAAe,EAAE,iBAAiB,CAAC,eAAe,EAAE,aAAa,CAY7E,CAAA;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAKhB,CAAA"}
@@ -0,0 +1,109 @@
1
+ import { z } from "zod";
2
+ import { McpToolError } from "./mcp-contract.js";
3
+ import { createTripComponentBodySchema, createTripEnvelopeSchema, priceTripSchema, reserveTripSchema, } from "./validation.js";
4
+ const createTripArgs = createTripEnvelopeSchema.extend({
5
+ components: z.array(createTripComponentBodySchema).default([]),
6
+ });
7
+ export const createTripTool = {
8
+ name: "create_trip",
9
+ description: "Create a deterministic trip envelope and optional components for a composed itinerary. " +
10
+ "Use this before pricing or reserving a cross-vertical trip.",
11
+ inputSchema: createTripArgs,
12
+ async handler(args, rawContext) {
13
+ const context = rawContext;
14
+ const composer = requireTrips(context);
15
+ const trip = await composer.createTrip({
16
+ title: args.title,
17
+ description: args.description,
18
+ travelerParty: args.travelerParty,
19
+ constraints: args.constraints,
20
+ createdBy: args.createdBy,
21
+ });
22
+ const components = [];
23
+ for (const component of args.components) {
24
+ components.push(await composer.addComponent({
25
+ ...component,
26
+ envelopeId: trip.envelope.id,
27
+ }));
28
+ }
29
+ return tripResult("Created trip", {
30
+ envelope: trip.envelope,
31
+ components,
32
+ });
33
+ },
34
+ };
35
+ const reviseTripArgs = z.object({
36
+ envelopeId: z.string().min(1),
37
+ addComponents: z.array(createTripComponentBodySchema).default([]),
38
+ removeComponentIds: z.array(z.string().min(1)).default([]),
39
+ });
40
+ export const reviseTripTool = {
41
+ name: "revise_trip",
42
+ description: "Revise a deterministic trip envelope by adding components or removing uncommitted components. " +
43
+ "This does not mutate committed bookings directly.",
44
+ inputSchema: reviseTripArgs,
45
+ async handler(args, rawContext) {
46
+ const context = rawContext;
47
+ const composer = requireTrips(context);
48
+ const added = [];
49
+ const removed = [];
50
+ for (const component of args.addComponents) {
51
+ added.push(await composer.addComponent({ ...component, envelopeId: args.envelopeId }));
52
+ }
53
+ if (args.removeComponentIds.length > 0 && !composer.removeComponent) {
54
+ throw new McpToolError("Trips MCP service removeComponent is not configured.", "MISSING_SERVICE", { service: "trips.removeComponent" });
55
+ }
56
+ for (const componentId of args.removeComponentIds) {
57
+ const result = await composer.removeComponent?.(componentId);
58
+ if (result)
59
+ removed.push(result);
60
+ }
61
+ return tripResult("Revised trip", {
62
+ envelopeId: args.envelopeId,
63
+ added,
64
+ removed,
65
+ });
66
+ },
67
+ };
68
+ export const priceTripTool = {
69
+ name: "price_trip",
70
+ description: "Price a deterministic trip through the trips. Returns aggregate totals, " +
71
+ "component statuses, warnings, failures, and quote expiry data.",
72
+ inputSchema: priceTripSchema,
73
+ async handler(args, rawContext) {
74
+ const context = rawContext;
75
+ const composer = requireTrips(context);
76
+ const result = await composer.priceTrip(args);
77
+ return tripResult("Priced trip", result);
78
+ },
79
+ };
80
+ export const reserveTripTool = {
81
+ name: "reserve_trip",
82
+ description: "Reserve a priced trip through deterministic trips services. " +
83
+ "Partial failures return explicit compensation and staff-remediation state.",
84
+ inputSchema: reserveTripSchema,
85
+ async handler(args, rawContext) {
86
+ const context = rawContext;
87
+ const composer = requireTrips(context);
88
+ const result = await composer.reserveTrip(args);
89
+ return tripResult("Reserved trip", result);
90
+ },
91
+ };
92
+ export const tripsMcpTools = [
93
+ createTripTool,
94
+ reviseTripTool,
95
+ priceTripTool,
96
+ reserveTripTool,
97
+ ];
98
+ function requireTrips(context) {
99
+ if (!context.trips) {
100
+ throw new McpToolError("MCP tool requires trips services to be wired into the context.", "MISSING_SERVICE", { service: "trips" });
101
+ }
102
+ return context.trips;
103
+ }
104
+ function tripResult(message, structuredContent) {
105
+ return {
106
+ content: [{ type: "text", text: message }],
107
+ structuredContent: structuredContent,
108
+ };
109
+ }