@zackbart/connecta 0.7.8 → 0.8.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/CHANGELOG.md +94 -0
- package/README.md +67 -144
- package/dist/activity.d.ts +1 -1
- package/dist/activity.d.ts.map +1 -1
- package/dist/activity.js.map +1 -1
- package/dist/auth/bearer.d.ts +1 -1
- package/dist/auth/bearer.js +4 -4
- package/dist/auth/bearer.js.map +1 -1
- package/dist/auth/clerk.d.ts +1 -1
- package/dist/auth/clerk.js +1 -1
- package/dist/call-admission.d.ts +81 -0
- package/dist/call-admission.d.ts.map +1 -0
- package/dist/call-admission.js +345 -0
- package/dist/call-admission.js.map +1 -0
- package/dist/catalog-fingerprint.d.ts +20 -0
- package/dist/catalog-fingerprint.d.ts.map +1 -0
- package/dist/catalog-fingerprint.js +34 -0
- package/dist/catalog-fingerprint.js.map +1 -0
- package/dist/catalog-limits.d.ts +10 -0
- package/dist/catalog-limits.d.ts.map +1 -0
- package/dist/catalog-limits.js +10 -0
- package/dist/catalog-limits.js.map +1 -0
- package/dist/catalog-service.d.ts +138 -0
- package/dist/catalog-service.d.ts.map +1 -0
- package/dist/catalog-service.js +407 -0
- package/dist/catalog-service.js.map +1 -0
- package/dist/catalog.js +2 -2
- package/dist/catalog.js.map +1 -1
- package/dist/concurrency.d.ts +4 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +31 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/connectors/api.d.ts +3 -1
- package/dist/connectors/api.d.ts.map +1 -1
- package/dist/connectors/api.js +22 -11
- package/dist/connectors/api.js.map +1 -1
- package/dist/connectors/remote-mcp.d.ts +3 -1
- package/dist/connectors/remote-mcp.d.ts.map +1 -1
- package/dist/connectors/remote-mcp.js +44 -18
- package/dist/connectors/remote-mcp.js.map +1 -1
- package/dist/credential-health.d.ts +0 -22
- package/dist/credential-health.d.ts.map +1 -1
- package/dist/credential-health.js +14 -10
- package/dist/credential-health.js.map +1 -1
- package/dist/credentials.d.ts +3 -2
- package/dist/credentials.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/execute.d.ts +9 -8
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +144 -291
- package/dist/execute.js.map +1 -1
- package/dist/executor-result.d.ts +0 -3
- package/dist/executor-result.d.ts.map +1 -1
- package/dist/executor-result.js +2 -2
- package/dist/executor-result.js.map +1 -1
- package/dist/executors/quickjs-child.js +3 -3
- package/dist/executors/quickjs-child.js.map +1 -1
- package/dist/executors/quickjs-protocol.d.ts +4 -1
- package/dist/executors/quickjs-protocol.d.ts.map +1 -1
- package/dist/executors/quickjs-runtime.d.ts.map +1 -1
- package/dist/executors/quickjs-runtime.js +7 -2
- package/dist/executors/quickjs-runtime.js.map +1 -1
- package/dist/executors/quickjs.d.ts.map +1 -1
- package/dist/executors/quickjs.js +4 -1
- package/dist/executors/quickjs.js.map +1 -1
- package/dist/favicon.js +2 -2
- package/dist/favicon.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -17
- package/dist/index.js.map +1 -1
- package/dist/invocation.d.ts +96 -0
- package/dist/invocation.d.ts.map +1 -0
- package/dist/invocation.js +369 -0
- package/dist/invocation.js.map +1 -0
- package/dist/meta-tools.d.ts +11 -86
- package/dist/meta-tools.d.ts.map +1 -1
- package/dist/meta-tools.js +145 -485
- package/dist/meta-tools.js.map +1 -1
- package/dist/operator-ui/generated.d.ts +3 -0
- package/dist/operator-ui/generated.d.ts.map +1 -0
- package/dist/operator-ui/generated.js +5 -0
- package/dist/operator-ui/generated.js.map +1 -0
- package/dist/operator-ui/model.d.ts +94 -0
- package/dist/operator-ui/model.d.ts.map +1 -0
- package/dist/operator-ui/model.js +28 -0
- package/dist/operator-ui/model.js.map +1 -0
- package/dist/registry.d.ts +47 -6
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +356 -35
- package/dist/registry.js.map +1 -1
- package/dist/routes/activity.d.ts +3 -0
- package/dist/routes/activity.d.ts.map +1 -0
- package/dist/routes/activity.js +173 -0
- package/dist/routes/activity.js.map +1 -0
- package/dist/routes/credentials.d.ts +3 -0
- package/dist/routes/credentials.d.ts.map +1 -0
- package/dist/routes/credentials.js +181 -0
- package/dist/routes/credentials.js.map +1 -0
- package/dist/routes/mcp.d.ts +8 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +383 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/oauth.d.ts +4 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +268 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/routes/shared.d.ts +97 -0
- package/dist/routes/shared.d.ts.map +1 -0
- package/dist/routes/shared.js +199 -0
- package/dist/routes/shared.js.map +1 -0
- package/dist/routes/ui.d.ts +3 -0
- package/dist/routes/ui.d.ts.map +1 -0
- package/dist/routes/ui.js +122 -0
- package/dist/routes/ui.js.map +1 -0
- package/dist/server.d.ts +9 -40
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +67 -1292
- package/dist/server.js.map +1 -1
- package/dist/skills.d.ts +0 -15
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +6 -5
- package/dist/skills.js.map +1 -1
- package/dist/storage/file.d.ts.map +1 -1
- package/dist/storage/file.js +3 -1
- package/dist/storage/file.js.map +1 -1
- package/dist/storage/memory.d.ts.map +1 -1
- package/dist/storage/memory.js +3 -1
- package/dist/storage/memory.js.map +1 -1
- package/dist/toolkits.d.ts +0 -22
- package/dist/toolkits.d.ts.map +1 -1
- package/dist/toolkits.js +2 -2
- package/dist/toolkits.js.map +1 -1
- package/dist/types.d.ts +64 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/ui.d.ts +3 -93
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +26 -1389
- package/dist/ui.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +15 -8
- package/src/activity.ts +5 -1
- package/src/auth/bearer.ts +4 -4
- package/src/auth/clerk.ts +1 -1
- package/src/call-admission.ts +522 -0
- package/src/catalog-fingerprint.ts +52 -0
- package/src/catalog-limits.ts +11 -0
- package/src/catalog-service.ts +601 -0
- package/src/catalog.ts +2 -2
- package/src/concurrency.ts +39 -0
- package/src/connectors/api.ts +25 -11
- package/src/connectors/remote-mcp.ts +55 -21
- package/src/credential-health.ts +13 -10
- package/src/credentials.ts +2 -2
- package/src/errors.ts +1 -1
- package/src/execute.ts +194 -377
- package/src/executor-result.ts +2 -2
- package/src/executors/quickjs-child.ts +8 -4
- package/src/executors/quickjs-protocol.ts +1 -1
- package/src/executors/quickjs-runtime.ts +5 -1
- package/src/executors/quickjs.ts +11 -8
- package/src/favicon.ts +2 -2
- package/src/index.ts +54 -17
- package/src/invocation.ts +527 -0
- package/src/meta-tools.ts +369 -797
- package/src/operator-ui/browser.css +413 -0
- package/src/operator-ui/browser.ts +1121 -0
- package/src/operator-ui/generated.ts +4 -0
- package/src/operator-ui/model.ts +127 -0
- package/src/registry.ts +489 -44
- package/src/routes/activity.ts +220 -0
- package/src/routes/credentials.ts +266 -0
- package/src/routes/mcp.ts +485 -0
- package/src/routes/oauth.ts +328 -0
- package/src/routes/shared.ts +330 -0
- package/src/routes/ui.ts +153 -0
- package/src/server.ts +70 -1702
- package/src/skills.ts +6 -5
- package/src/storage/file.ts +3 -1
- package/src/storage/memory.ts +3 -1
- package/src/toolkits.ts +2 -2
- package/src/types.ts +70 -2
- package/src/ui.ts +52 -1489
- package/src/version.ts +1 -1
|
@@ -9,10 +9,12 @@ import { ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
|
9
9
|
import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/cfworker";
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
import { KvOAuthProvider } from "../auth/downstream-oauth.js";
|
|
12
|
+
import { MAX_CATALOG_TOOLS } from "../catalog-limits.js";
|
|
12
13
|
import { ConnectorCallError } from "../errors.js";
|
|
13
14
|
import { CONNECTA_VERSION } from "../version.js";
|
|
14
15
|
import type {
|
|
15
16
|
Connector,
|
|
17
|
+
ConnectorCallAdmissionPolicy,
|
|
16
18
|
ConnectorContext,
|
|
17
19
|
ConnectorStatus,
|
|
18
20
|
Logger,
|
|
@@ -38,6 +40,8 @@ export interface RemoteMcpOptions {
|
|
|
38
40
|
* and is ignored.
|
|
39
41
|
*/
|
|
40
42
|
maxResultBytes?: number;
|
|
43
|
+
/** Optional per-runtime downstream call-admission policy. */
|
|
44
|
+
callAdmission?: ConnectorCallAdmissionPolicy;
|
|
41
45
|
/**
|
|
42
46
|
* Optional agent-facing usage guide (markdown) served by the `skills`
|
|
43
47
|
* meta-tool as `connector:<id>`. See `Connector.usageGuide`.
|
|
@@ -106,18 +110,16 @@ const TERMINATE_SESSION_BUDGET_MS = 1_000;
|
|
|
106
110
|
* cap the bytes a caller can be made to hold, not the number of round trips it
|
|
107
111
|
* took to get them.
|
|
108
112
|
*/
|
|
109
|
-
const MAX_TOOLS = 100_000;
|
|
110
|
-
|
|
111
113
|
/**
|
|
112
114
|
* Absolute backstop on `tools/list` pages in one refresh — a runaway guard, not
|
|
113
115
|
* the primary defense.
|
|
114
116
|
*
|
|
115
117
|
* The walk terminates on its own well before this: a cursor handed back twice
|
|
116
118
|
* is a definite loop, two consecutive pages that add no new tools are a server
|
|
117
|
-
* going nowhere, and
|
|
118
|
-
* only so the loop is finite even if a downstream somehow
|
|
119
|
-
* forever on a path with no discovery deadline. Set high
|
|
120
|
-
* server reaches it.
|
|
119
|
+
* going nowhere, and MAX_CATALOG_TOOLS caps what any of it can accumulate.
|
|
120
|
+
* This exists only so the loop is finite even if a downstream somehow
|
|
121
|
+
* satisfies all three forever on a path with no discovery deadline. Set high
|
|
122
|
+
* enough that no honest server reaches it.
|
|
121
123
|
*/
|
|
122
124
|
const MAX_TOOL_PAGES = 10_000;
|
|
123
125
|
|
|
@@ -295,7 +297,9 @@ function redirectedInit(init: RequestInit, status: number): RequestInit {
|
|
|
295
297
|
if (!becomesGet) return init;
|
|
296
298
|
const headers = new Headers(init.headers);
|
|
297
299
|
for (const name of BODY_HEADERS) headers.delete(name);
|
|
298
|
-
|
|
300
|
+
const redirected = { ...init, method: "GET", headers };
|
|
301
|
+
delete redirected.body;
|
|
302
|
+
return redirected;
|
|
299
303
|
}
|
|
300
304
|
|
|
301
305
|
/**
|
|
@@ -543,10 +547,14 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
|
|
|
543
547
|
const url = new URL(opts.url);
|
|
544
548
|
const guardedFetch = redirectSafeFetch(id, opts.redirects);
|
|
545
549
|
if (opts.auth?.type === "oauth") {
|
|
550
|
+
// The SDK class declares `sessionId` as an own `string | undefined`
|
|
551
|
+
// property while its Transport interface declares it optional. They are
|
|
552
|
+
// runtime-compatible; exact optional types only exposes that declaration
|
|
553
|
+
// mismatch at this boundary.
|
|
546
554
|
return new StreamableHTTPClientTransport(url, {
|
|
547
555
|
authProvider: provider ?? newProvider(ctx),
|
|
548
556
|
fetch: guardedFetch,
|
|
549
|
-
});
|
|
557
|
+
}) as unknown as Transport;
|
|
550
558
|
}
|
|
551
559
|
const headers =
|
|
552
560
|
opts.auth?.type === "headers" ? opts.auth.headers : undefined;
|
|
@@ -556,7 +564,7 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
|
|
|
556
564
|
...(headers ? { requestInit: { headers } } : {}),
|
|
557
565
|
fetch: guardedFetch,
|
|
558
566
|
},
|
|
559
|
-
);
|
|
567
|
+
) as unknown as Transport;
|
|
560
568
|
};
|
|
561
569
|
|
|
562
570
|
const reset = (state: ConnectionState) => {
|
|
@@ -739,11 +747,18 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
|
|
|
739
747
|
|
|
740
748
|
const connector: Connector = {
|
|
741
749
|
id,
|
|
742
|
-
title: opts.title,
|
|
750
|
+
...(opts.title !== undefined ? { title: opts.title } : {}),
|
|
743
751
|
kind: "mcp",
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
752
|
+
...(opts.description !== undefined
|
|
753
|
+
? { description: opts.description }
|
|
754
|
+
: {}),
|
|
755
|
+
...(opts.maxResultBytes !== undefined
|
|
756
|
+
? { maxResultBytes: opts.maxResultBytes }
|
|
757
|
+
: {}),
|
|
758
|
+
...(opts.callAdmission !== undefined
|
|
759
|
+
? { callAdmission: opts.callAdmission }
|
|
760
|
+
: {}),
|
|
761
|
+
...(opts.usageGuide !== undefined ? { usageGuide: opts.usageGuide } : {}),
|
|
747
762
|
|
|
748
763
|
// `tools/list` is cursor-paginated: the server chooses the page size and
|
|
749
764
|
// signals "there is more" with a `nextCursor`, which the SDK's
|
|
@@ -826,9 +841,9 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
|
|
|
826
841
|
}
|
|
827
842
|
// Checked here rather than on arrival: this bounds what a *walk* may
|
|
828
843
|
// accumulate; a one-page server was always free to send its page.
|
|
829
|
-
if (listed.length >
|
|
844
|
+
if (listed.length > MAX_CATALOG_TOOLS) {
|
|
830
845
|
throw new Error(
|
|
831
|
-
`Connector "${id}" advertised further tools/list pages past ${listed.length} tools, over the ${
|
|
846
|
+
`Connector "${id}" advertised further tools/list pages past ${listed.length} tools, over the ${MAX_CATALOG_TOOLS}-tool ceiling one catalog refresh will collect.`,
|
|
832
847
|
);
|
|
833
848
|
}
|
|
834
849
|
// Opaque by contract: handed straight back, never parsed, rewritten,
|
|
@@ -859,10 +874,28 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
|
|
|
859
874
|
primeToolMetadata(client, listed);
|
|
860
875
|
return listed.map((t) => ({
|
|
861
876
|
name: t.name,
|
|
862
|
-
description: t.description,
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
877
|
+
...(t.description !== undefined ? { description: t.description } : {}),
|
|
878
|
+
...(t.inputSchema !== undefined
|
|
879
|
+
? {
|
|
880
|
+
inputSchema: t.inputSchema as NonNullable<
|
|
881
|
+
ToolDef["inputSchema"]
|
|
882
|
+
>,
|
|
883
|
+
}
|
|
884
|
+
: {}),
|
|
885
|
+
...(t.outputSchema !== undefined
|
|
886
|
+
? {
|
|
887
|
+
outputSchema: t.outputSchema as NonNullable<
|
|
888
|
+
ToolDef["outputSchema"]
|
|
889
|
+
>,
|
|
890
|
+
}
|
|
891
|
+
: {}),
|
|
892
|
+
...(t.annotations !== undefined
|
|
893
|
+
? {
|
|
894
|
+
annotations: t.annotations as NonNullable<
|
|
895
|
+
ToolDef["annotations"]
|
|
896
|
+
>,
|
|
897
|
+
}
|
|
898
|
+
: {}),
|
|
866
899
|
}));
|
|
867
900
|
},
|
|
868
901
|
|
|
@@ -938,7 +971,7 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
|
|
|
938
971
|
const url = await getProvider(ctx, state).pendingAuthorizationUrl();
|
|
939
972
|
return {
|
|
940
973
|
state: "auth_required",
|
|
941
|
-
authorizationUrl: url,
|
|
974
|
+
...(url !== undefined ? { authorizationUrl: url } : {}),
|
|
942
975
|
message: "Authorization required — open the URL to connect.",
|
|
943
976
|
};
|
|
944
977
|
}
|
|
@@ -1009,9 +1042,10 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
|
|
|
1009
1042
|
};
|
|
1010
1043
|
} catch (err) {
|
|
1011
1044
|
if (state.authRequired) {
|
|
1045
|
+
const authorizationUrl = await p.pendingAuthorizationUrl();
|
|
1012
1046
|
return {
|
|
1013
1047
|
state: "auth_required",
|
|
1014
|
-
authorizationUrl:
|
|
1048
|
+
...(authorizationUrl !== undefined ? { authorizationUrl } : {}),
|
|
1015
1049
|
message: "Authorization required — open the URL to connect.",
|
|
1016
1050
|
};
|
|
1017
1051
|
}
|
package/src/credential-health.ts
CHANGED
|
@@ -117,8 +117,8 @@ export interface CredentialHealthConfig {
|
|
|
117
117
|
onRequest?: boolean;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
const DEFAULT_CREDENTIAL_CHECK_INTERVAL_SECONDS = 900;
|
|
121
|
+
const DEFAULT_CREDENTIAL_CHECK_CONCURRENCY = 4;
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
124
|
* How long a read of one connector's record is served from memory before going
|
|
@@ -362,7 +362,7 @@ export interface CredentialCheckOptions {
|
|
|
362
362
|
* their back. A connector whose only hook cannot test its declared shape is
|
|
363
363
|
* checkable only if it also implements `status()`.
|
|
364
364
|
*/
|
|
365
|
-
|
|
365
|
+
function isCheckableConnector(connector: Connector): boolean {
|
|
366
366
|
const hasCredentialStore = Boolean(
|
|
367
367
|
connector.credential || connector.hasStoredCredential,
|
|
368
368
|
);
|
|
@@ -408,8 +408,9 @@ function testHookFor(
|
|
|
408
408
|
}
|
|
409
409
|
// A single-value shape with nothing under the reserved field is still nothing
|
|
410
410
|
// to test, so the stored value gets the last word even when the rule fits.
|
|
411
|
-
|
|
412
|
-
|
|
411
|
+
const storedValue = storedValues.value;
|
|
412
|
+
if (mode === "single" && typeof storedValue === "string") {
|
|
413
|
+
return (ctx) => connector.testCredential!(storedValue, ctx);
|
|
413
414
|
}
|
|
414
415
|
return undefined;
|
|
415
416
|
}
|
|
@@ -420,14 +421,16 @@ async function mapWithConcurrency<T, R>(
|
|
|
420
421
|
limit: number,
|
|
421
422
|
fn: (item: T) => Promise<R>,
|
|
422
423
|
): Promise<R[]> {
|
|
423
|
-
const out =
|
|
424
|
-
|
|
424
|
+
const out = Array<R>(items.length);
|
|
425
|
+
const remaining = items.entries();
|
|
425
426
|
const workers = Array.from(
|
|
426
427
|
{ length: Math.min(limit, items.length) },
|
|
427
428
|
async () => {
|
|
428
|
-
|
|
429
|
-
const
|
|
430
|
-
|
|
429
|
+
for (;;) {
|
|
430
|
+
const next = remaining.next();
|
|
431
|
+
if (next.done) return;
|
|
432
|
+
const [index, item] = next.value;
|
|
433
|
+
out[index] = await fn(item);
|
|
431
434
|
}
|
|
432
435
|
},
|
|
433
436
|
);
|
package/src/credentials.ts
CHANGED
|
@@ -24,7 +24,7 @@ interface CredentialPlaintext {
|
|
|
24
24
|
updatedBy: string;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
interface CredentialFieldMetadata {
|
|
28
28
|
configured: true;
|
|
29
29
|
/** Only emitted when the value is long enough that four chars don't leak much. */
|
|
30
30
|
lastFour?: string;
|
|
@@ -41,7 +41,7 @@ export interface CredentialMetadata {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/** Which hook a testable credential is checked with. */
|
|
44
|
-
|
|
44
|
+
type CredentialTestMode = "single" | "multiple";
|
|
45
45
|
|
|
46
46
|
/** Operator-safe explanation shared by every surface that detects shape drift. */
|
|
47
47
|
export const STORED_CREDENTIAL_SHAPE_MISMATCH_ERROR =
|
package/src/errors.ts
CHANGED
|
@@ -49,7 +49,7 @@ export class ConnectorCallError extends Error {
|
|
|
49
49
|
* the assignment would not keep it off the instance. Keeping the window out
|
|
50
50
|
* of the wire format is `classifyCallError`'s job, not this constructor's.
|
|
51
51
|
*/
|
|
52
|
-
readonly retryAfterMs
|
|
52
|
+
readonly retryAfterMs: number | undefined;
|
|
53
53
|
|
|
54
54
|
constructor(
|
|
55
55
|
code: ConnectorCallErrorCode,
|