@cat-factory/mcp-server 0.2.1 → 0.3.1

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.
@@ -14,8 +14,10 @@ import { CAT_FACTORY_OMITTED_OPERATIONS, CAT_FACTORY_TOOL_GROUPS } from './tools
14
14
  * free to disagree with the first.
15
15
  */
16
16
  export function buildInstructions(selection) {
17
- const { exposed, filteredGroups, writeToolsHidden } = selection;
17
+ const { exposed, filteredGroups, writeToolsHidden, deniedTools, toolsAllowListed } = selection;
18
18
  const groups = [...new Set(exposed.map((tool) => tool.group))];
19
+ // Nullable entries so a section that has nothing to say can decline to appear, rather than every
20
+ // caller having to keep the push order in step with the narrative order by hand.
19
21
  const sections = [
20
22
  "cat-factory runs coding agents against a team's real repositories: a board of services and " +
21
23
  'tasks, each task run through a pipeline of agent steps that opens and merges pull requests. ' +
@@ -23,12 +25,19 @@ export function buildInstructions(selection) {
23
25
  `Available tool groups:\n${groups
24
26
  .map((group) => `- ${group}: ${CAT_FACTORY_TOOL_GROUPS[group]}`)
25
27
  .join('\n')}`,
26
- 'Two things here cost real money and real time, so confirm with the user before calling them: ' +
27
- '`tasks_start` / `tasks_retry` and `jobs_create` each begin an agent run against a real ' +
28
- 'repository, and `notifications_act` can merge a pull request. Everything else is cheap.',
28
+ costlyTools(exposed),
29
29
  'A run PARKS on a human decision and then waits indefinitely by design; it is not stuck. Read ' +
30
30
  'the park with `decisions_list` and answer it with the other `decisions_*` tools, or leave ' +
31
31
  'it for a person.',
32
+ // The two absent operations are the platform's live channels, so "how do I watch a run" is the
33
+ // question this surface most needs answered in prose. Without it a model either invents a
34
+ // streaming tool, calls the poll in a tight loop, or reports one non-terminal reading as the
35
+ // outcome, and the last of those is the one nobody catches, because it looks like an answer.
36
+ 'To WATCH work, poll rather than stream: `tasks_get_run` for a task run, `jobs_get` for a ' +
37
+ 'headless job. An agent step takes minutes, so poll every 15-30 seconds and say so to the ' +
38
+ 'user instead of going quiet. Keep polling until the status is terminal (`done`, `failed`, ' +
39
+ '`cancelled`) or until `decisions_list` shows a park to answer; anything else is a run still ' +
40
+ 'in flight, and reporting it as the outcome is wrong rather than early.',
32
41
  'Results are JSON. Lists are keyset-paginated: pass the `cursor` a page returns to get the ' +
33
42
  'next one, and stop when it comes back null (an empty page with a cursor is normal).',
34
43
  ];
@@ -40,10 +49,62 @@ export function buildInstructions(selection) {
40
49
  sections.push(`The operator switched off these tool groups on THIS server: ${filteredGroups.join(', ')}. ` +
41
50
  'The deployment still supports them; they are not reachable from here.');
42
51
  }
52
+ // The per-tool filters are stated in the same voice and for the same reason as the group one. The
53
+ // deny-list matters most: it is the filter an operator reaches for to keep ONE capability away
54
+ // from a model, and a model that reads the absence as a missing platform feature will offer to do
55
+ // it some other way instead of asking the person who switched it off.
56
+ if (deniedTools.length > 0) {
57
+ sections.push(`The operator withheld these individual tools on THIS server: ${deniedTools.join(', ')}. ` +
58
+ 'The deployment still supports them; do not look for another route to the same effect.');
59
+ }
60
+ if (toolsAllowListed) {
61
+ sections.push("This server exposes an explicitly chosen subset of the deployment's tools, so what you " +
62
+ 'can see is not the whole API. Everything listed works; anything you expect and cannot ' +
63
+ 'find was left out here on purpose.');
64
+ }
43
65
  // The omissions are stated in the same voice as the filters above, and for the same reason: a
44
66
  // model that cannot find a way to watch a run live should learn that the platform streams and
45
67
  // that a tool call is the wrong shape for it, rather than concluding the platform does not.
46
68
  sections.push(`Not available as tools:\n${CAT_FACTORY_OMITTED_OPERATIONS.map((omitted) => `- ${omitted.route}: ${omitted.reason}`).join('\n')}`);
47
- return sections.join('\n\n');
69
+ return sections.filter(Boolean).join('\n\n');
70
+ }
71
+ /**
72
+ * The "check with a human first" section, or null when nothing exposed here needs one.
73
+ *
74
+ * DERIVED from the generated table's own `destructive` hint rather than restating the tool names in
75
+ * prose: a list written here would be a second declaration of which tools spend, free to disagree
76
+ * with the one a host reads off the annotations, and it would go on naming a tool the operator has
77
+ * withheld on this server. A model told to be careful with a tool it cannot see learns that this
78
+ * prose is not about the server in front of it.
79
+ */
80
+ function costlyTools(exposed) {
81
+ const costly = exposed.filter((tool) => tool.hints?.destructive);
82
+ if (costly.length === 0)
83
+ return null;
84
+ const exposes = (name) => costly.some((tool) => tool.name === name);
85
+ const lines = [
86
+ 'Confirm with the user before calling these, because each does something a person cannot ' +
87
+ `simply undo: ${costly.map((tool) => `\`${tool.name}\``).join(', ')}.`,
88
+ ];
89
+ // Each consequence is stated only where the tool that has it survived the filters, for the same
90
+ // reason the names are derived rather than restated: prose describing a capability this server does
91
+ // not serve teaches a model that the prose is not about the server in front of it.
92
+ if (['tasks_start', 'tasks_retry', 'jobs_create'].some(exposes)) {
93
+ lines.push('Starting, retrying or creating work begins an agent run against a real repository: real ' +
94
+ 'model spend, real time.');
95
+ }
96
+ if (exposes('notifications_act')) {
97
+ lines.push('Acting on a notification can merge a pull request.');
98
+ }
99
+ if (exposes('tasks_delete')) {
100
+ lines.push('A deleted task does not come back.');
101
+ }
102
+ // Only where there IS something else. A filter can narrow this server down to the spending tools
103
+ // alone (an allow-list naming just `tasks_start` is the realistic one), and a closing sentence
104
+ // about everything else would then be describing tools the model cannot see, which teaches it
105
+ // that this prose is not about the server in front of it.
106
+ if (exposed.length > costly.length)
107
+ lines.push('Everything else here is cheap.');
108
+ return lines.join(' ');
48
109
  }
49
110
  //# sourceMappingURL=instructions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAE9F,8FAA8F;AAC9F,EAAE;AACF,iGAAiG;AACjG,4FAA4F;AAC5F,+FAA+F;AAC/F,gGAAgG;AAChG,2EAA2E;AAE3E;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAwB;IACxD,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,GAAG,SAAS,CAAA;IAC/D,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC9D,MAAM,QAAQ,GAAa;QACzB,6FAA6F;YAC3F,8FAA8F;YAC9F,yFAAyF;QAC3F,2BAA2B,MAAM;aAC9B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,KAAK,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;aAC/D,IAAI,CAAC,IAAI,CAAC,EAAE;QACf,+FAA+F;YAC7F,yFAAyF;YACzF,yFAAyF;QAC3F,+FAA+F;YAC7F,4FAA4F;YAC5F,kBAAkB;QACpB,4FAA4F;YAC1F,qFAAqF;KACxF,CAAA;IACD,IAAI,gBAAgB,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CACX,yFAAyF;YACvF,6EAA6E,CAChF,CAAA;IACH,CAAC;IACD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CACX,+DAA+D,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAC1F,uEAAuE,CAC1E,CAAA;IACH,CAAC;IACD,8FAA8F;IAC9F,8FAA8F;IAC9F,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,CACX,4BAA4B,8BAA8B,CAAC,GAAG,CAC5D,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,MAAM,EAAE,CACrD,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACf,CAAA;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC"}
1
+ {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"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"}
package/dist/result.d.ts CHANGED
@@ -23,6 +23,7 @@ export type ToolResult = {
23
23
  type: 'text';
24
24
  text: string;
25
25
  }[];
26
+ structuredContent?: Record<string, unknown>;
26
27
  isError?: boolean;
27
28
  };
28
29
  /**
@@ -31,10 +32,16 @@ export type ToolResult = {
31
32
  * A `204` endpoint resolves to `undefined`, which is a real answer ("it worked, there is nothing
32
33
  * to return") and not an empty one, so it is SAID rather than rendered as `undefined` or as an
33
34
  * empty string a model would read as a failure.
35
+ *
36
+ * The JSON is COMPACT. Two-space indentation reads better to a human than to a model and costs
37
+ * roughly a third of every result in whitespace, which on this surface is a third of an
38
+ * agent-context snapshot; a host that wants it pretty can re-print the structured content it also
39
+ * gets back.
34
40
  */
35
41
  export declare function renderResult(value: unknown, options: {
36
42
  maxChars?: number;
37
43
  toolName: string;
44
+ structured?: boolean;
38
45
  }): ToolResult;
39
46
  /**
40
47
  * Render a failure as tool content.
@@ -1 +1 @@
1
- {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,SAAU,CAAA;AAE/C;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAQD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC/C,UAAU,CAiBZ;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CA+BrF"}
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,SAAU,CAAA;AAE/C;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAQD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACrE,UAAU,CA8BZ;AA8CD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CA+BrF"}
package/dist/result.js CHANGED
@@ -23,24 +23,78 @@ function text(value, isError = false) {
23
23
  * A `204` endpoint resolves to `undefined`, which is a real answer ("it worked, there is nothing
24
24
  * to return") and not an empty one, so it is SAID rather than rendered as `undefined` or as an
25
25
  * empty string a model would read as a failure.
26
+ *
27
+ * The JSON is COMPACT. Two-space indentation reads better to a human than to a model and costs
28
+ * roughly a third of every result in whitespace, which on this surface is a third of an
29
+ * agent-context snapshot; a host that wants it pretty can re-print the structured content it also
30
+ * gets back.
26
31
  */
27
32
  export function renderResult(value, options) {
28
33
  if (value === undefined) {
29
- return text('The request succeeded. This endpoint returns no content.');
34
+ // A tool that declares an output schema may not answer successfully with no structured content:
35
+ // the caller's own client raises a PROTOCOL error for that, which is not shown to the model at
36
+ // all. So an empty body from an operation the spec says answers with one takes the same
37
+ // deployment-disagrees-with-the-schema route as a non-object below, rather than the honest
38
+ // "returns no content" that belongs to a `204` operation (which declares no schema).
39
+ return options.structured
40
+ ? text(schemaMismatch(options.toolName, 'answered with no body at all'), true)
41
+ : text('The request succeeded. This endpoint returns no content.');
30
42
  }
31
43
  const maxChars = options.maxChars ?? DEFAULT_MAX_RESULT_CHARS;
32
- const json = JSON.stringify(value, null, 2);
33
- if (json.length <= maxChars)
44
+ const json = JSON.stringify(value);
45
+ if (json.length > maxChars)
46
+ return text(overCap(options.toolName, json.length, maxChars), true);
47
+ if (!options.structured)
34
48
  return text(json);
35
- // The note goes FIRST and names the truncation in the same breath as the remedy: what follows
36
- // is no longer parseable JSON, and a model that starts reading at the top must know that before
37
- // it starts, not after it has already summarised half a document as complete.
38
- const dropped = json.length - maxChars;
39
- const note = `[TRUNCATED] \`${options.toolName}\` returned ${json.length} characters, over this server's ` +
40
- `${maxChars}-character limit; the last ${dropped} were dropped. What follows is the beginning ` +
41
- 'of the response and is NOT valid JSON. Narrow the request instead of reading on: list ' +
42
- 'endpoints take `limit` and `cursor`, and the debug text reads take `offset`.';
43
- return text(`${note}\n\n${json.slice(0, maxChars)}`);
49
+ if (!isJsonObject(value)) {
50
+ // The tool DECLARES an output schema, so the protocol obliges a successful result to carry
51
+ // structured content, and this value cannot be any. Reported as a failure of the call rather
52
+ // than dropped to text, because it means the deployment answered with something the published
53
+ // schema does not describe, and a caller silently getting the text form would never find out.
54
+ return text(schemaMismatch(options.toolName, `returned a ${describeJson(value)}`) +
55
+ ` The response was: ${json}`, true);
56
+ }
57
+ // Both halves, which is what the protocol asks of a tool that returns structured content: the
58
+ // text block is what a host with no structured-content support shows the model, and the
59
+ // structured half is what an agent framework consumes without re-parsing prose.
60
+ return { content: [{ type: 'text', text: json }], structuredContent: value };
61
+ }
62
+ /**
63
+ * The message for a result that does not fit.
64
+ *
65
+ * A REFUSAL, where this used to render the first `maxChars` under a `[TRUNCATED]` note. Two reasons
66
+ * it changed together: a tool declaring an `outputSchema` may not answer successfully without
67
+ * structured content, and half an object cannot satisfy the schema it was cut out of, and the old
68
+ * note itself told the model that what followed was not valid JSON and to narrow instead of reading
69
+ * on, which is a hundred thousand characters of context spent to deliver that instruction.
70
+ */
71
+ function overCap(toolName, length, maxChars) {
72
+ return (`${toolName} returned ${length} characters, over this server's ${maxChars}-character limit, ` +
73
+ 'so none of it was rendered: a response cut off mid-object is not valid JSON, and a model ' +
74
+ 'reading the surviving half summarises it as though it were whole. Narrow the request and ' +
75
+ 'call again (list endpoints take `limit` and `cursor`, and the debug text reads take ' +
76
+ '`offset`), or raise CAT_FACTORY_MCP_MAX_RESULT_CHARS on this server.');
77
+ }
78
+ /**
79
+ * The message for a response the published output schema does not describe.
80
+ *
81
+ * One wording for both shapes of the same fault, because the fix is the same one either way: this
82
+ * package and the deployment it is pointed at disagree about what an operation answers with, and
83
+ * only an upgrade of one of them settles it. Reported as a failed CALL rather than left to the
84
+ * caller's client, whose protocol-level refusal never reaches the model.
85
+ */
86
+ function schemaMismatch(toolName, what) {
87
+ return (`${toolName} ${what}, where its published output schema describes an object. This is a ` +
88
+ 'mismatch between the deployment and this server, not something the arguments caused: check ' +
89
+ 'that the two are on compatible versions.');
90
+ }
91
+ function isJsonObject(value) {
92
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
93
+ }
94
+ function describeJson(value) {
95
+ if (value === null)
96
+ return 'null';
97
+ return Array.isArray(value) ? 'array' : typeof value;
44
98
  }
45
99
  /**
46
100
  * Render a failure as tool content.
@@ -1 +1 @@
1
- {"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { type CatFactoryMcpOptions } from './config.ts';
3
3
  import { type CatFactoryTool } from './tools.generated.ts';
4
4
  /** The npm version, stamped into the SDK's `User-Agent` so a deployment can attribute calls. */
5
- export declare const MCP_SERVER_VERSION = "0.2.1";
5
+ export declare const MCP_SERVER_VERSION = "0.3.1";
6
6
  /** The name this server reports to a host. */
7
7
  export declare const MCP_SERVER_NAME = "cat-factory";
8
8
  export interface CatFactoryMcpServer {
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAElE,OAAO,EAAE,KAAK,oBAAoB,EAAe,MAAM,aAAa,CAAA;AAGpE,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAgB7E,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAEzC,8CAA8C;AAC9C,eAAO,MAAM,eAAe,gBAAgB,CAAA;AAE5C,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;CACjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CAwE5F"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAElE,OAAO,EAAE,KAAK,oBAAoB,EAAe,MAAM,aAAa,CAAA;AAGpE,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAgB7E,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAEzC,8CAA8C;AAC9C,eAAO,MAAM,eAAe,gBAAgB,CAAA;AAE5C,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;CACjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CA+E5F"}
package/dist/server.js CHANGED
@@ -19,7 +19,7 @@ import { CAT_FACTORY_TOOLS } from './tools.generated.js';
19
19
  // has been round-tripped through a second type system, and every gap in that conversion becomes a
20
20
  // tool that misdescribes its own input.
21
21
  /** The npm version, stamped into the SDK's `User-Agent` so a deployment can attribute calls. */
22
- export const MCP_SERVER_VERSION = '0.2.1';
22
+ export const MCP_SERVER_VERSION = '0.3.1';
23
23
  /** The name this server reports to a host. */
24
24
  export const MCP_SERVER_NAME = 'cat-factory';
25
25
  /**
@@ -55,13 +55,19 @@ export function createCatFactoryMcpServer(options) {
55
55
  title: tool.title,
56
56
  description: tool.description,
57
57
  inputSchema: tool.inputSchema,
58
+ // Declared only where the operation has an object to describe (a `204` has none). A tool that
59
+ // declares one is then OBLIGED to return `structuredContent` on every success, which is why
60
+ // `renderResult` refuses an over-cap result rather than truncating it.
61
+ ...(tool.outputSchema ? { outputSchema: tool.outputSchema } : {}),
58
62
  annotations: {
59
63
  title: tool.title,
60
- // The only annotation this facade can state truthfully. `readOnlyHint` follows from the
61
- // HTTP method; `destructiveHint` and `idempotentHint` are deliberately left unset rather
62
- // than guessed, because a DELETE here is idempotent AND destructive and the defaults a
63
- // host assumes for an unset hint are safer than a wrong one.
64
+ // `readOnlyHint` follows from the HTTP method. The other two come from the generated table
65
+ // and are present only where the consequence is real money or a merged pull request; where
66
+ // they are absent the protocol's own defaults apply, which are the cautious ones.
64
67
  readOnlyHint: tool.readOnly,
68
+ ...(tool.hints
69
+ ? { destructiveHint: tool.hints.destructive, idempotentHint: tool.hints.idempotent }
70
+ : {}),
65
71
  },
66
72
  })),
67
73
  }));
@@ -80,6 +86,7 @@ export function createCatFactoryMcpServer(options) {
80
86
  const result = await tool.invoke(client, args);
81
87
  return renderResult(result, {
82
88
  toolName: tool.name,
89
+ structured: tool.outputSchema !== undefined,
83
90
  ...(options.maxResultChars !== undefined ? { maxChars: options.maxResultChars } : {}),
84
91
  });
85
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { type EnvReadDeps } from './config.ts';
3
+ /** What the boot needs from the process around it. */
4
+ export interface StdioBootDeps extends EnvReadDeps {
5
+ /** The environment the options are read from. */
6
+ env: Record<string, string | undefined>;
7
+ /** Where every human-readable byte goes. NEVER stdout. */
8
+ log: (line: string) => void;
9
+ /**
10
+ * Attach the built server to a transport.
11
+ *
12
+ * Defaults to the real stdio transport. A test overrides it rather than the whole server, so
13
+ * everything up to and including the connect ordering below is the code that actually ships.
14
+ */
15
+ connect?: (server: Server) => Promise<void>;
16
+ }
17
+ /** What the boot reports back, so a caller can say it in its own words. */
18
+ export interface StdioBootResult {
19
+ toolCount: number;
20
+ baseUrl: string;
21
+ }
22
+ /**
23
+ * Build the server from the environment and connect it.
24
+ *
25
+ * The transport is connected BEFORE the ready line is written. A host reads that line as "this
26
+ * server is up"; writing it first would mean announcing readiness and then failing to connect, which
27
+ * is the one ordering that produces a log claiming success next to a server that never served.
28
+ */
29
+ export declare function bootStdioServer(deps: StdioBootDeps): Promise<StdioBootResult>;
30
+ /**
31
+ * What to write when the boot failed.
32
+ *
33
+ * It names the configuration rather than only the error, because every way this fails is a
34
+ * configuration problem and the operator reading it is looking at a host's config file: the cause
35
+ * says what is wrong and the second line says where to fix it.
36
+ */
37
+ export declare function startupFailureMessage(error: unknown): string;
38
+ //# sourceMappingURL=stdio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAEvE,OAAO,EAAY,KAAK,WAAW,EAAkB,MAAM,aAAa,CAAA;AAaxE,sDAAsD;AACtD,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACvC,0DAA0D;IAC1D,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5C;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAUnF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM5D"}
package/dist/stdio.js ADDED
@@ -0,0 +1,31 @@
1
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
+ import { ENV_VARS, optionsFromEnv } from './config.js';
3
+ import { createCatFactoryMcpServer } from './server.js';
4
+ /**
5
+ * Build the server from the environment and connect it.
6
+ *
7
+ * The transport is connected BEFORE the ready line is written. A host reads that line as "this
8
+ * server is up"; writing it first would mean announcing readiness and then failing to connect, which
9
+ * is the one ordering that produces a log claiming success next to a server that never served.
10
+ */
11
+ export async function bootStdioServer(deps) {
12
+ const options = optionsFromEnv(deps.env, deps.readSecretFile ? { readSecretFile: deps.readSecretFile } : {});
13
+ const { server, tools } = createCatFactoryMcpServer(options);
14
+ const connect = deps.connect ?? ((built) => built.connect(new StdioServerTransport()));
15
+ await connect(server);
16
+ deps.log(`cat-factory MCP server ready: ${tools.length} tools against ${options.baseUrl}\n`);
17
+ return { toolCount: tools.length, baseUrl: options.baseUrl };
18
+ }
19
+ /**
20
+ * What to write when the boot failed.
21
+ *
22
+ * It names the configuration rather than only the error, because every way this fails is a
23
+ * configuration problem and the operator reading it is looking at a host's config file: the cause
24
+ * says what is wrong and the second line says where to fix it.
25
+ */
26
+ export function startupFailureMessage(error) {
27
+ const message = error instanceof Error ? error.message : String(error);
28
+ return (`cat-factory MCP server failed to start: ${message}\n` +
29
+ `Configure it with ${ENV_VARS.baseUrl} and either ${ENV_VARS.apiKey} or ${ENV_VARS.apiKeyFile}.\n`);
30
+ }
31
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,QAAQ,EAAoB,cAAc,EAAE,MAAM,aAAa,CAAA;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAiCvD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAmB;IACvD,MAAM,OAAO,GAAG,cAAc,CAC5B,IAAI,CAAC,GAAG,EACR,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CACnE,CAAA;IACD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAA;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC,CAAA;IAC9F,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IACrB,IAAI,CAAC,GAAG,CAAC,iCAAiC,KAAK,CAAC,MAAM,kBAAkB,OAAO,CAAC,OAAO,IAAI,CAAC,CAAA;IAC5F,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAA;AAC9D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACtE,OAAO,CACL,2CAA2C,OAAO,IAAI;QACtD,qBAAqB,QAAQ,CAAC,OAAO,eAAe,QAAQ,CAAC,MAAM,OAAO,QAAQ,CAAC,UAAU,KAAK,CACnG,CAAA;AACH,CAAC"}
@@ -11,6 +11,15 @@ export interface CatFactoryTool {
11
11
  operationId: string;
12
12
  /** Whether the call changes nothing (a GET). Hosts use it to decide what needs confirming. */
13
13
  readOnly: boolean;
14
+ /**
15
+ * The annotations the HTTP method cannot supply, present only where the consequence is real
16
+ * money or a merged pull request. Absent means the protocol's own cautious defaults apply
17
+ * (`destructiveHint` true, `idempotentHint` false), which is never worse than the truth.
18
+ */
19
+ hints?: {
20
+ destructive: boolean;
21
+ idempotent: boolean;
22
+ };
14
23
  description: string;
15
24
  inputSchema: {
16
25
  type: 'object';
@@ -18,6 +27,19 @@ export interface CatFactoryTool {
18
27
  required?: readonly string[];
19
28
  additionalProperties: false;
20
29
  };
30
+ /**
31
+ * The shape of a successful result, absent when the operation answers with no body.
32
+ *
33
+ * Rendered permissively ON PURPOSE: no `required`, no `enum`, no closed `anyOf`, no length or
34
+ * range bounds, and for a union not even `type`. A caller's MCP client VALIDATES a result against
35
+ * this, and `/api/v1` is additive forever, so every one of those would be a way for an older copy
36
+ * of this package to reject a newer deployment's honest answer. What is left is the field names and
37
+ * their types, plus the known members of a vocabulary named in prose.
38
+ */
39
+ outputSchema?: {
40
+ type: 'object';
41
+ properties: Record<string, unknown>;
42
+ };
21
43
  /** Forward the validated arguments to the SDK. */
22
44
  invoke: (client: CatFactoryClient, args: Record<string, unknown>) => Promise<unknown>;
23
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tools.generated.d.ts","sourceRoot":"","sources":["../src/tools.generated.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAA;IACnB,8FAA8F;IAC9F,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAA;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACnC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC5B,oBAAoB,EAAE,KAAK,CAAA;KAC5B,CAAA;IACD,kDAAkD;IAClD,MAAM,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACtF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf;AAwCD,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EAmXtD,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,EAAE,SAAS,0BAA0B,EAa/E,CAAA;AAED,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASpE,CAAA"}
1
+ {"version":3,"file":"tools.generated.d.ts","sourceRoot":"","sources":["../src/tools.generated.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAA;IACnB,8FAA8F;IAC9F,QAAQ,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAA;IACrD,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAA;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACnC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC5B,oBAAoB,EAAE,KAAK,CAAA;KAC5B,CAAA;IACD;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,QAAQ,CAAA;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACpC,CAAA;IACD,kDAAkD;IAClD,MAAM,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACtF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf;AAwCD,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EA4ZtD,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,EAAE,SAAS,0BAA0B,EAa/E,CAAA;AAED,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASpE,CAAA"}