@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.
- package/README.md +123 -28
- package/dist/bin.js +11 -19
- package/dist/bin.js.map +1 -1
- package/dist/config.d.ts +29 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +102 -10
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +66 -5
- package/dist/instructions.js.map +1 -1
- package/dist/result.d.ts +7 -0
- package/dist/result.d.ts.map +1 -1
- package/dist/result.js +66 -12
- package/dist/result.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +12 -5
- package/dist/server.js.map +1 -1
- package/dist/stdio.d.ts +38 -0
- package/dist/stdio.d.ts.map +1 -0
- package/dist/stdio.js +31 -0
- package/dist/stdio.js.map +1 -0
- package/dist/tools.generated.d.ts +22 -0
- package/dist/tools.generated.d.ts.map +1 -1
- package/dist/tools.generated.js +43 -2
- package/dist/tools.generated.js.map +1 -1
- package/package.json +2 -2
package/dist/instructions.js
CHANGED
|
@@ -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
|
-
|
|
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
|
package/dist/instructions.js.map
CHANGED
|
@@ -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;
|
|
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.
|
package/dist/result.d.ts.map
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
33
|
-
if (json.length
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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.
|
package/dist/result.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAEtE,iGAAiG;AACjG,iGAAiG;AACjG,4DAA4D;AAE5D;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAEtE,iGAAiG;AACjG,iGAAiG;AACjG,4DAA4D;AAE5D;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,OAAO,CAAA;AAkB/C,SAAS,IAAI,CAAC,KAAa,EAAE,OAAO,GAAG,KAAK;IAC1C,OAAO,OAAO;QACZ,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;QAC7D,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;AAClD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAc,EACd,OAAsE;IAEtE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,gGAAgG;QAChG,+FAA+F;QAC/F,wFAAwF;QACxF,2FAA2F;QAC3F,qFAAqF;QACrF,OAAO,OAAO,CAAC,UAAU;YACvB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,8BAA8B,CAAC,EAAE,IAAI,CAAC;YAC9E,CAAC,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAA;IACtE,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,wBAAwB,CAAA;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAClC,IAAI,IAAI,CAAC,MAAM,GAAG,QAAQ;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAA;IAC/F,IAAI,CAAC,OAAO,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1C,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,2FAA2F;QAC3F,6FAA6F;QAC7F,8FAA8F;QAC9F,8FAA8F;QAC9F,OAAO,IAAI,CACT,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACnE,sBAAsB,IAAI,EAAE,EAC9B,IAAI,CACL,CAAA;IACH,CAAC;IACD,8FAA8F;IAC9F,wFAAwF;IACxF,gFAAgF;IAChF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAA;AAC9E,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,OAAO,CAAC,QAAgB,EAAE,MAAc,EAAE,QAAgB;IACjE,OAAO,CACL,GAAG,QAAQ,aAAa,MAAM,mCAAmC,QAAQ,oBAAoB;QAC7F,2FAA2F;QAC3F,2FAA2F;QAC3F,sFAAsF;QACtF,sEAAsE,CACvE,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,cAAc,CAAC,QAAgB,EAAE,IAAY;IACpD,OAAO,CACL,GAAG,QAAQ,IAAI,IAAI,qEAAqE;QACxF,6FAA6F;QAC7F,0CAA0C,CAC3C,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAA;IACjC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAA;AACtD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,OAA6B;IACvE,IAAI,KAAK,YAAY,kBAAkB,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG;YACZ,GAAG,OAAO,CAAC,QAAQ,iBAAiB,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,GAAG;YAClE,KAAK,CAAC,OAAO;SACd,CAAA;QACD,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CACR,iCAAiC,EACjC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,CAAC,IAAI,IAAI,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAClF,CAAA;QACH,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1D,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACzD,CAAC;QACD,4FAA4F;QAC5F,sFAAsF;QACtF,IAAI,KAAK,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAA;IACrC,CAAC;IACD,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;QACrC,4FAA4F;QAC5F,8FAA8F;QAC9F,iCAAiC;QACjC,OAAO,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,YAAY,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,CAAA;IAClF,CAAC;IACD,+FAA+F;IAC/F,2FAA2F;IAC3F,mDAAmD;IACnD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACtE,OAAO,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,yBAAyB,OAAO,EAAE,EAAE,IAAI,CAAC,CAAA;AAC1E,CAAC"}
|
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.
|
|
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 {
|
package/dist/server.d.ts.map
CHANGED
|
@@ -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,
|
|
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.
|
|
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
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
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
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAA;AAClG,OAAO,EAA6B,WAAW,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAuB,MAAM,sBAAsB,CAAA;AAE7E,uFAAuF;AACvF,EAAE;AACF,8FAA8F;AAC9F,iGAAiG;AACjG,gGAAgG;AAChG,+FAA+F;AAC/F,uDAAuD;AACvD,EAAE;AACF,gGAAgG;AAChG,2FAA2F;AAC3F,iGAAiG;AACjG,kGAAkG;AAClG,wCAAwC;AAExC,gGAAgG;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAA;AAEzC,8CAA8C;AAC9C,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAA;AAS5C;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAA6B;IACrE,MAAM,SAAS,GAAG,WAAW,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;IACzD,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,CAAA;IAC7B,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC;QAClC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,yFAAyF;QACzF,0FAA0F;QAC1F,4DAA4D;QAC5D,SAAS,EAAE,mBAAmB,kBAAkB,EAAE;QAClD,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnD,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,kBAAkB,EAAE,EACtD;QACE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAC3B,YAAY,EAAE,iBAAiB,CAAC,SAAS,CAAC;KAC3C,CACF,CAAA;IAED,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC;QACtD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE;gBACX,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/stdio.d.ts
ADDED
|
@@ -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,
|
|
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"}
|