@zackbart/connecta 0.10.6 → 0.12.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.
- package/AGENTS.md +8 -6
- package/CHANGELOG.md +80 -0
- package/README.md +5 -4
- package/bin/connecta.mjs +0 -7
- package/dist/activity.d.ts.map +1 -1
- package/dist/activity.js.map +1 -1
- package/dist/apps-shell.d.ts +38 -0
- package/dist/apps-shell.d.ts.map +1 -0
- package/dist/apps-shell.js +175 -0
- package/dist/apps-shell.js.map +1 -0
- package/dist/catalog-service.d.ts +2 -17
- package/dist/catalog-service.d.ts.map +1 -1
- package/dist/catalog-service.js +4 -6
- package/dist/catalog-service.js.map +1 -1
- package/dist/connectors/api.d.ts +2 -2
- package/dist/connectors/remote-mcp.d.ts +1 -1
- package/dist/errors.d.ts +1 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/execute.d.ts +37 -8
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +137 -42
- package/dist/execute.js.map +1 -1
- package/dist/executor-admission.d.ts +8 -0
- package/dist/executor-admission.d.ts.map +1 -1
- package/dist/executor-admission.js +11 -0
- package/dist/executor-admission.js.map +1 -1
- package/dist/executors/quickjs.d.ts.map +1 -1
- package/dist/executors/quickjs.js +2 -2
- package/dist/executors/quickjs.js.map +1 -1
- package/dist/index.d.ts +15 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -37
- package/dist/index.js.map +1 -1
- package/dist/invocation.js +2 -2
- package/dist/invocation.js.map +1 -1
- package/dist/meta-tools.d.ts +19 -58
- package/dist/meta-tools.d.ts.map +1 -1
- package/dist/meta-tools.js +34 -431
- package/dist/meta-tools.js.map +1 -1
- package/dist/registry.d.ts +1 -10
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +3 -15
- package/dist/registry.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +67 -30
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/shared.d.ts +5 -11
- package/dist/routes/shared.d.ts.map +1 -1
- package/dist/routes/shared.js.map +1 -1
- package/dist/server.js +5 -4
- package/dist/server.js.map +1 -1
- package/dist/skills.d.ts +8 -18
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +13 -60
- package/dist/skills.js.map +1 -1
- package/dist/types.d.ts +6 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/code-first-exploration.md +16 -16
- package/documentation/code-mode.md +130 -41
- package/documentation/connectors.md +1 -1
- package/documentation/mcp-2026-07-28.md +1 -1
- package/documentation/mcp-ui-design.md +382 -0
- package/documentation/meta-tools.md +30 -43
- package/documentation/rich-output-design.md +4 -4
- package/ethos.md +7 -2
- package/examples/node/README.md +1 -2
- package/examples/node/src/index.ts +1 -3
- package/examples/worker/README.md +8 -13
- package/examples/worker/src/index.ts +6 -14
- package/examples/worker/wrangler.jsonc +3 -6
- package/package.json +1 -1
- package/src/activity.ts +5 -0
- package/src/apps-shell.ts +179 -0
- package/src/catalog-service.ts +6 -26
- package/src/connectors/api.ts +2 -2
- package/src/connectors/remote-mcp.ts +1 -1
- package/src/errors.ts +2 -2
- package/src/execute.ts +150 -49
- package/src/executor-admission.ts +12 -0
- package/src/executors/quickjs.ts +2 -1
- package/src/index.ts +40 -69
- package/src/invocation.ts +2 -2
- package/src/meta-tools.ts +38 -565
- package/src/registry.ts +2 -33
- package/src/routes/mcp.ts +79 -30
- package/src/routes/shared.ts +4 -11
- package/src/server.ts +7 -7
- package/src/skills.ts +11 -74
- package/src/types.ts +6 -21
- package/src/version.ts +1 -1
- package/templates/node/README.md +2 -1
- package/templates/node/package.json +1 -1
- package/templates/node/src/index.ts +1 -1
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* One MCP endpoint aggregating a downstream remote MCP and an HTTP API, guarded
|
|
5
5
|
* by Clerk OAuth *and* a static bearer token, with OAuth/cache state in a KV
|
|
6
|
-
* namespace.
|
|
7
|
-
* seven-tool
|
|
6
|
+
* namespace. The required Worker Loader binding in wrangler.jsonc backs the
|
|
7
|
+
* seven-tool surface.
|
|
8
8
|
*
|
|
9
9
|
* Setup (this example has no package.json of its own — it self-references the
|
|
10
10
|
* installed `@zackbart/connecta` package):
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
* and CLERK_PUBLISHABLE_KEY + PUBLIC_URL as plain vars in wrangler.jsonc.
|
|
20
20
|
* 4. Enable Dynamic Client Registration in the Clerk dashboard
|
|
21
21
|
* (OAuth Applications -> DCR toggle) so Claude/Cursor can self-register.
|
|
22
|
-
* 5.
|
|
23
|
-
* wrangler.jsonc. Binding presence enables execute_code automatically.
|
|
22
|
+
* 5. Use the Workers Paid plan required by the `worker_loaders` binding.
|
|
24
23
|
* 6. `wrangler deploy` from this folder (examples/worker), where wrangler.jsonc
|
|
25
24
|
* lives. Point your MCP client at `<PUBLIC_URL>/mcp`.
|
|
26
25
|
*/
|
|
@@ -46,23 +45,16 @@ interface Env {
|
|
|
46
45
|
PUBLIC_URL: string;
|
|
47
46
|
/**
|
|
48
47
|
* Worker Loader binding (wrangler.jsonc `worker_loaders`) powering
|
|
49
|
-
* execute_code
|
|
50
|
-
* the Workers Paid plan; leave the binding absent for the nine classic
|
|
51
|
-
* meta-tools on either plan.
|
|
48
|
+
* execute_code. Dynamic Workers require the Workers Paid plan.
|
|
52
49
|
*/
|
|
53
|
-
LOADER
|
|
50
|
+
LOADER: WorkerLoader;
|
|
54
51
|
}
|
|
55
52
|
|
|
56
53
|
function build(env: Env) {
|
|
57
54
|
return createConnecta({
|
|
58
55
|
publicUrl: env.PUBLIC_URL,
|
|
59
56
|
storage: cloudflareKvStorage(env.CONNECTA_KV),
|
|
60
|
-
|
|
61
|
-
// mode and the seven-tool code-first surface with it; leaving it absent
|
|
62
|
-
// keeps this deployment free-tier compatible on the classic surface.
|
|
63
|
-
...(env.LOADER
|
|
64
|
-
? { executor: new DynamicWorkerExecutor({ loader: env.LOADER }) }
|
|
65
|
-
: {}),
|
|
57
|
+
executor: new DynamicWorkerExecutor({ loader: env.LOADER }),
|
|
66
58
|
auth: [
|
|
67
59
|
// Multiple credentials may identify callers in one deployment. Every
|
|
68
60
|
// admitted caller reaches this deployment's deliberate connector set.
|
|
@@ -16,11 +16,8 @@
|
|
|
16
16
|
// Create with `wrangler kv namespace create CONNECTA_KV` and paste the id.
|
|
17
17
|
"kv_namespaces": [
|
|
18
18
|
{ "binding": "CONNECTA_KV", "id": "replace-with-kv-namespace-id" }
|
|
19
|
-
]
|
|
19
|
+
],
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
// serves the seven-tool code-first surface. Leave it absent for a free-tier
|
|
24
|
-
// deployment with the nine classic meta-tools.
|
|
25
|
-
// "worker_loaders": [{ "binding": "LOADER" }]
|
|
21
|
+
// Required by execute_code; Dynamic Workers use the Workers Paid plan.
|
|
22
|
+
"worker_loaders": [{ "binding": "LOADER" }]
|
|
26
23
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "One MCP to rule them all — a single MCP endpoint aggregating many downstream connectors behind a code-first surface of seven meta-tools.",
|
package/src/activity.ts
CHANGED
|
@@ -23,6 +23,11 @@ const MAX_ACTIVITY_ADDRESS_BYTES = MAX_ACTIVITY_NAME_BYTES * 2 + 1;
|
|
|
23
23
|
export type ActivityCallSource =
|
|
24
24
|
| "call_tool"
|
|
25
25
|
| "call_destructive_tool"
|
|
26
|
+
// Read-only history. Nothing emits `batch_call` since issue #273 removed the
|
|
27
|
+
// tool, but activity storage is append-only: rows written by older
|
|
28
|
+
// deployments are still read back — the D1 example maps a stored row straight
|
|
29
|
+
// into this type — and an operator's timeline should not have to lie about
|
|
30
|
+
// where a call came from. Never widen this member back into a live source.
|
|
26
31
|
| "batch_call"
|
|
27
32
|
| "execute_code";
|
|
28
33
|
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one MCP Apps template connecta serves (`U5`, `U6`).
|
|
3
|
+
*
|
|
4
|
+
* A build-time string constant, not a file read at startup: the core is
|
|
5
|
+
* Web-API-only so it runs unchanged on Workers, and the same bytes have to
|
|
6
|
+
* serve everywhere. The shell is display-only — it renders whatever HTML a
|
|
7
|
+
* program handed `connecta.ui` inside a nested `srcdoc` frame and forwards no
|
|
8
|
+
* channel back from that frame to the host, so program-authored markup is
|
|
9
|
+
* inert beyond its own pixels.
|
|
10
|
+
*
|
|
11
|
+
* The address carries a version segment because hosts are permitted to
|
|
12
|
+
* prefetch and cache templates by URI: change these bytes, bump `v1`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** The only `ui://` URI in the system. No program input reaches it. */
|
|
16
|
+
export const PROGRAM_UI_RESOURCE_URI = "ui://connecta/program-ui/v1";
|
|
17
|
+
|
|
18
|
+
/** The mimeType the Apps spec requires of an HTML template. */
|
|
19
|
+
export const PROGRAM_UI_MIME_TYPE = "text/html;profile=mcp-app";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The result `_meta` key carrying the payload (`U3`). A plain single-label
|
|
23
|
+
* prefix rather than the reverse-DNS form MCP's SHOULD prefers: connecta has
|
|
24
|
+
* no domain to reverse, and fabricating one to satisfy a SHOULD is a worse
|
|
25
|
+
* answer than the shape the key format's MUST already permits.
|
|
26
|
+
*/
|
|
27
|
+
export const PROGRAM_UI_META_KEY = "connecta/ui";
|
|
28
|
+
|
|
29
|
+
/** The one extension identifier connecta advertises (`U11`). */
|
|
30
|
+
export const MCP_APPS_EXTENSION = "io.modelcontextprotocol/ui";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The shell document. Dependency-free and deliberately small: it speaks the
|
|
34
|
+
* Apps postMessage dialect (`ui/initialize`, `ui/notifications/initialized`,
|
|
35
|
+
* `ui/notifications/tool-result`, `ui/notifications/size-changed`,
|
|
36
|
+
* `ui/resource-teardown`), lifts `_meta["connecta/ui"].html` out of the
|
|
37
|
+
* delivered tool result, and puts it in a frame. It declares no CSP domains,
|
|
38
|
+
* so the host applies its restrictive default and the `srcdoc` frame inherits
|
|
39
|
+
* `default-src 'none'` — the payload gets scripts and local interactivity,
|
|
40
|
+
* and no network.
|
|
41
|
+
*/
|
|
42
|
+
export const PROGRAM_UI_SHELL_HTML = `<!doctype html>
|
|
43
|
+
<html lang="en">
|
|
44
|
+
<head>
|
|
45
|
+
<meta charset="utf-8" />
|
|
46
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
47
|
+
<title>connecta program view</title>
|
|
48
|
+
<style>
|
|
49
|
+
html,
|
|
50
|
+
body {
|
|
51
|
+
margin: 0;
|
|
52
|
+
padding: 0;
|
|
53
|
+
background: transparent;
|
|
54
|
+
}
|
|
55
|
+
#program-view {
|
|
56
|
+
display: block;
|
|
57
|
+
width: 100%;
|
|
58
|
+
min-height: 480px;
|
|
59
|
+
border: 0;
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
62
|
+
</head>
|
|
63
|
+
<body>
|
|
64
|
+
<iframe
|
|
65
|
+
id="program-view"
|
|
66
|
+
title="Program-rendered view"
|
|
67
|
+
sandbox="allow-scripts"
|
|
68
|
+
srcdoc=""
|
|
69
|
+
></iframe>
|
|
70
|
+
<script>
|
|
71
|
+
(function () {
|
|
72
|
+
"use strict";
|
|
73
|
+
// The host frame is the only peer this shell speaks to, in either
|
|
74
|
+
// direction. The payload frame below is sandboxed to scripts alone,
|
|
75
|
+
// with no same-origin escape, and is never handed a reply path:
|
|
76
|
+
// anything it posts fails the source check and is dropped. There is
|
|
77
|
+
// no bridge from program HTML to the host, by construction rather
|
|
78
|
+
// than by validation.
|
|
79
|
+
var host = window.parent;
|
|
80
|
+
var view = document.getElementById("program-view");
|
|
81
|
+
var initializeId = "connecta-ui-initialize";
|
|
82
|
+
var lastWidth = 0;
|
|
83
|
+
var lastHeight = 0;
|
|
84
|
+
|
|
85
|
+
function send(message) {
|
|
86
|
+
if (!host || host === window) return;
|
|
87
|
+
host.postMessage(message, "*");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function notify(method, params) {
|
|
91
|
+
send({ jsonrpc: "2.0", method: method, params: params });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Program views are fixed-height by construction. The shell has no
|
|
95
|
+
// bridge to the payload frame — that is the security posture, not an
|
|
96
|
+
// omission — so it can never learn the payload's content height, and
|
|
97
|
+
// what it reports here is its own box: the min-height above, unless
|
|
98
|
+
// the host has given it more. Taller content scrolls inside the inner
|
|
99
|
+
// frame rather than growing the view. Raising the min-height is the
|
|
100
|
+
// only lever; a content-height signal would cost the isolation.
|
|
101
|
+
function reportSize() {
|
|
102
|
+
var width = Math.ceil(document.documentElement.clientWidth);
|
|
103
|
+
var height = Math.ceil(document.documentElement.scrollHeight);
|
|
104
|
+
if (width === lastWidth && height === lastHeight) return;
|
|
105
|
+
lastWidth = width;
|
|
106
|
+
lastHeight = height;
|
|
107
|
+
notify("ui/notifications/size-changed", {
|
|
108
|
+
width: width,
|
|
109
|
+
height: height
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function payloadHtml(result) {
|
|
114
|
+
if (!result || typeof result !== "object") return null;
|
|
115
|
+
var meta = result._meta;
|
|
116
|
+
if (!meta || typeof meta !== "object") return null;
|
|
117
|
+
var payload = meta["connecta/ui"];
|
|
118
|
+
if (!payload || typeof payload !== "object") return null;
|
|
119
|
+
var html = payload.html;
|
|
120
|
+
return typeof html === "string" && html.length > 0 ? html : null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function render(params) {
|
|
124
|
+
var html =
|
|
125
|
+
payloadHtml(params) ||
|
|
126
|
+
payloadHtml(params && params.result) ||
|
|
127
|
+
payloadHtml(params && params.toolResult);
|
|
128
|
+
if (html === null) return;
|
|
129
|
+
view.srcdoc = html;
|
|
130
|
+
reportSize();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
window.addEventListener("message", function (event) {
|
|
134
|
+
if (event.source !== host) return;
|
|
135
|
+
var message = event.data;
|
|
136
|
+
if (!message || message.jsonrpc !== "2.0") return;
|
|
137
|
+
if (message.method === "ui/notifications/tool-result") {
|
|
138
|
+
render(message.params);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (message.method === "ui/resource-teardown") {
|
|
142
|
+
// A host->view request, not a notification: the host waits for
|
|
143
|
+
// this reply before it tears the view down. There is nothing to
|
|
144
|
+
// release, so answer immediately rather than make it time out.
|
|
145
|
+
if (message.id !== undefined && message.id !== null) {
|
|
146
|
+
send({ jsonrpc: "2.0", id: message.id, result: {} });
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Only a completed handshake earns "initialized". A JSON-RPC error
|
|
151
|
+
// response carries the same id, and announcing initialization on one
|
|
152
|
+
// would assert a handshake that never happened.
|
|
153
|
+
if (message.id === initializeId && message.result !== undefined) {
|
|
154
|
+
notify("ui/notifications/initialized", {});
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
window.addEventListener("resize", reportSize);
|
|
159
|
+
view.addEventListener("load", reportSize);
|
|
160
|
+
|
|
161
|
+
// Every field here is required by the Apps initialize schema, and a
|
|
162
|
+
// conforming host rejects the request outright when one is missing —
|
|
163
|
+
// which would strand the shell before any tool result arrives.
|
|
164
|
+
send({
|
|
165
|
+
jsonrpc: "2.0",
|
|
166
|
+
id: initializeId,
|
|
167
|
+
method: "ui/initialize",
|
|
168
|
+
params: {
|
|
169
|
+
appInfo: { name: "connecta program view", version: "1" },
|
|
170
|
+
appCapabilities: {},
|
|
171
|
+
protocolVersion: "2026-01-26"
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
reportSize();
|
|
175
|
+
})();
|
|
176
|
+
</script>
|
|
177
|
+
</body>
|
|
178
|
+
</html>
|
|
179
|
+
`;
|
package/src/catalog-service.ts
CHANGED
|
@@ -48,23 +48,10 @@ const MAX_QUERY_ANALYSIS_TERM_LENGTH = 64;
|
|
|
48
48
|
|
|
49
49
|
const encoder = new TextEncoder();
|
|
50
50
|
|
|
51
|
-
/**
|
|
52
|
-
* The tool a describe-path error should name when it tells a caller to retry.
|
|
53
|
-
* This is the route the *caller* took, not the deployment's advertised surface:
|
|
54
|
-
* a classic deployment with an executor serves `describe_tools` at top level
|
|
55
|
-
* while every in-program describe still arrives through `connecta.describe`, so
|
|
56
|
-
* one CatalogService cannot infer the answer from `surface` alone. Callers pass
|
|
57
|
-
* the route they own.
|
|
58
|
-
*/
|
|
59
|
-
export type DescribeRoute = "describe_tools" | "connecta.describe";
|
|
60
|
-
|
|
61
51
|
/**
|
|
62
52
|
* The discovery route a routing failure should send a caller back through. Same
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* options separate for: `search_tools` exists on both advertised surfaces, so a
|
|
66
|
-
* top-level handler never has to derive this one, while an in-program caller
|
|
67
|
-
* still has to be told about `connecta.search` because it cannot call a tool.
|
|
53
|
+
* catalog logic serves both the top-level `search_tools` path and the
|
|
54
|
+
* in-program `connecta.search` path, so callers pass the route they own.
|
|
68
55
|
*/
|
|
69
56
|
export type SearchRoute = "search_tools" | "connecta.search";
|
|
70
57
|
|
|
@@ -96,10 +83,7 @@ function discoverySearchLimit(value: unknown): number {
|
|
|
96
83
|
}
|
|
97
84
|
|
|
98
85
|
/** Normalize the single-address convenience form, then validate the bounded list. */
|
|
99
|
-
function discoveryAddresses(
|
|
100
|
-
args: CatalogDescribeArgs,
|
|
101
|
-
describeRoute: DescribeRoute,
|
|
102
|
-
): unknown[] {
|
|
86
|
+
function discoveryAddresses(args: CatalogDescribeArgs): unknown[] {
|
|
103
87
|
if (args.address !== undefined && args.addresses !== undefined) {
|
|
104
88
|
throw new DiscoveryPolicyError(
|
|
105
89
|
"invalid_args",
|
|
@@ -121,7 +105,7 @@ function discoveryAddresses(
|
|
|
121
105
|
if (value.length > MAX_DESCRIBE_ADDRESSES) {
|
|
122
106
|
throw new DiscoveryPolicyError(
|
|
123
107
|
"invalid_args",
|
|
124
|
-
`addresses must contain at most ${MAX_DESCRIBE_ADDRESSES} entries. Split a larger list across
|
|
108
|
+
`addresses must contain at most ${MAX_DESCRIBE_ADDRESSES} entries. Split a larger list across connecta.describe calls.`,
|
|
125
109
|
);
|
|
126
110
|
}
|
|
127
111
|
return value;
|
|
@@ -327,7 +311,6 @@ export class CatalogService {
|
|
|
327
311
|
readonly requestScope: object;
|
|
328
312
|
private readonly probeTimeoutMs: number;
|
|
329
313
|
private readonly concurrency: number;
|
|
330
|
-
private readonly describeRoute: DescribeRoute;
|
|
331
314
|
private readonly searchRoute: SearchRoute;
|
|
332
315
|
private readonly loaded = new Map<string, ToolDef[]>();
|
|
333
316
|
private readonly loading = new Map<string, Promise<ToolDef[]>>();
|
|
@@ -339,8 +322,6 @@ export class CatalogService {
|
|
|
339
322
|
requestScope?: object;
|
|
340
323
|
probeTimeoutMs?: number;
|
|
341
324
|
concurrency?: number;
|
|
342
|
-
/** The tool describe-path errors name. Default `describe_tools`. */
|
|
343
|
-
describeRoute?: DescribeRoute;
|
|
344
325
|
/** The discovery route recovery records name. Default `search_tools`. */
|
|
345
326
|
searchRoute?: SearchRoute;
|
|
346
327
|
} = {},
|
|
@@ -349,7 +330,6 @@ export class CatalogService {
|
|
|
349
330
|
this.probeTimeoutMs =
|
|
350
331
|
normalizeTimeoutMs(options.probeTimeoutMs) ?? DEFAULT_PROBE_TIMEOUT_MS;
|
|
351
332
|
this.concurrency = resolveDiscoveryConcurrency(options.concurrency);
|
|
352
|
-
this.describeRoute = options.describeRoute ?? "describe_tools";
|
|
353
333
|
this.searchRoute = options.searchRoute ?? "search_tools";
|
|
354
334
|
}
|
|
355
335
|
|
|
@@ -817,7 +797,7 @@ export class CatalogService {
|
|
|
817
797
|
}
|
|
818
798
|
|
|
819
799
|
async describe(args: CatalogDescribeArgs): Promise<CatalogDescription[]> {
|
|
820
|
-
const addresses = discoveryAddresses(args
|
|
800
|
+
const addresses = discoveryAddresses(args);
|
|
821
801
|
const format = args.format ?? "compact";
|
|
822
802
|
const resolved = addresses.map((rawAddress) => {
|
|
823
803
|
const address = String(rawAddress);
|
|
@@ -834,7 +814,7 @@ export class CatalogService {
|
|
|
834
814
|
connectorIds,
|
|
835
815
|
this.concurrency,
|
|
836
816
|
(id) =>
|
|
837
|
-
this.loadForDiscovery(id,
|
|
817
|
+
this.loadForDiscovery(id, `connecta.describe probe of "${id}"`),
|
|
838
818
|
);
|
|
839
819
|
const catalogs = new Map<string, ToolDef[] | Error>();
|
|
840
820
|
loaded.forEach((result, index) => {
|
package/src/connectors/api.ts
CHANGED
|
@@ -20,7 +20,7 @@ export interface ApiTool {
|
|
|
20
20
|
outputSchema?: JsonSchema;
|
|
21
21
|
/**
|
|
22
22
|
* Standard MCP-style behavior hints. Only an explicit readOnlyHint: true
|
|
23
|
-
* admits the tool to call_tool
|
|
23
|
+
* admits the tool to call_tool and execute_code.
|
|
24
24
|
*/
|
|
25
25
|
annotations?: ToolAnnotations;
|
|
26
26
|
handler: (args: any, ctx: ConnectorContext) => Promise<unknown> | unknown;
|
|
@@ -32,7 +32,7 @@ export interface ApiOptions {
|
|
|
32
32
|
description?: string;
|
|
33
33
|
/**
|
|
34
34
|
* Max inline result size (bytes) for this connector's tools before
|
|
35
|
-
* call_tool
|
|
35
|
+
* call_tool truncates and stashes the full text for get_result
|
|
36
36
|
* paging. Overrides the deployment's `calls.maxResultBytes`; omit to inherit
|
|
37
37
|
* it. Must be a whole number of bytes >= 1; anything else warns at startup
|
|
38
38
|
* and is ignored.
|
|
@@ -38,7 +38,7 @@ export interface RemoteMcpOptions {
|
|
|
38
38
|
description?: string;
|
|
39
39
|
/**
|
|
40
40
|
* Max inline result size (bytes) for this connector's tools before
|
|
41
|
-
* call_tool
|
|
41
|
+
* call_tool truncates and stashes the full text for get_result
|
|
42
42
|
* paging. Overrides the deployment's `calls.maxResultBytes`; omit to inherit
|
|
43
43
|
* it. Must be a whole number of bytes >= 1; anything else warns at startup
|
|
44
44
|
* and is ignored.
|
package/src/errors.ts
CHANGED
|
@@ -221,7 +221,7 @@ export class ConnectorCallError extends Error {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
/** The `error` object surfaced in
|
|
224
|
+
/** The `error` object surfaced in value-mode call results and connecta.batch entries. */
|
|
225
225
|
export interface CallErrorDetails {
|
|
226
226
|
code: string;
|
|
227
227
|
message: string;
|
|
@@ -322,7 +322,7 @@ const RETRYABLE_MESSAGE_RE =
|
|
|
322
322
|
const TIMEOUT_MESSAGE_RE = /timed out|timeout/i;
|
|
323
323
|
|
|
324
324
|
/** Message-text fallback used when an error carries no typed classification. */
|
|
325
|
-
|
|
325
|
+
function messageLooksRetryable(message: string): boolean {
|
|
326
326
|
return RETRYABLE_MESSAGE_RE.test(message);
|
|
327
327
|
}
|
|
328
328
|
|