managed-deepagents 0.6.2-dev.20 → 0.6.2-dev.22
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 +12 -9
- package/dist/agent-auth.d.ts +16 -2
- package/dist/agent-auth.d.ts.map +1 -1
- package/dist/agent-auth.js +112 -12
- package/dist/agent-auth.js.map +1 -1
- package/dist/channels/manifest.d.ts +4 -2
- package/dist/channels/manifest.d.ts.map +1 -1
- package/dist/connections.d.ts +63 -0
- package/dist/connections.d.ts.map +1 -0
- package/dist/{credentials.js → connections.js} +74 -100
- package/dist/connections.js.map +1 -0
- package/dist/connectors/mcp/index.d.ts +5 -5
- package/dist/connectors/mcp/index.d.ts.map +1 -1
- package/dist/connectors/mcp/index.js +60 -44
- package/dist/connectors/mcp/index.js.map +1 -1
- package/dist/connectors/mcp/schema.d.ts.map +1 -1
- package/dist/connectors/mcp/schema.js +5 -3
- package/dist/connectors/mcp/schema.js.map +1 -1
- package/dist/connectors/mcp/types.d.ts +8 -8
- package/dist/connectors/mcp/types.d.ts.map +1 -1
- package/dist/credential-gate.d.ts +13 -12
- package/dist/credential-gate.d.ts.map +1 -1
- package/dist/credential-gate.js +49 -31
- package/dist/credential-gate.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +7 -7
- package/dist/credentials.d.ts +0 -95
- package/dist/credentials.d.ts.map +0 -1
- package/dist/credentials.js.map +0 -1
|
@@ -1,58 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `
|
|
2
|
+
* `connections.get(...)` — read a managed connection from a tool.
|
|
3
3
|
*
|
|
4
|
-
* `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* current caller, always backed by an OAuth grant. Resolution reads Agent Auth
|
|
8
|
-
* on every await and never caches.
|
|
4
|
+
* `{ type: "agent" }` resolves shared workspace material on the connection row.
|
|
5
|
+
* `{ type: "user" }` resolves per-caller grants (OAuth or opaque). Resolution
|
|
6
|
+
* reads Agent Auth on every await and never caches.
|
|
9
7
|
*
|
|
10
|
-
* `mda dev`
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* an actionable error. Both scopes work normally against a deployment.
|
|
8
|
+
* `mda dev` substitutes local values for agent opaque secrets via `MDA_DEV_*`.
|
|
9
|
+
* User-owned connections need a deployment; opaque user grants use the same
|
|
10
|
+
* pre-run gate as OAuth.
|
|
14
11
|
*/
|
|
15
12
|
import { AGENT_AUTH_TIMEOUT_MS, AgentAuth, CredentialAuthorizationRequiredError, CredentialStoreError, } from "./agent-auth.js";
|
|
16
13
|
import { buildRuntimeIdentity, resolveRuntimeConfigurable, } from "./runtime/identity-runtime.js";
|
|
17
14
|
export { AGENT_AUTH_TIMEOUT_MS, AgentAuthUnknownProviderError, CredentialAuthorizationRequiredError, CredentialStoreError, } from "./agent-auth.js";
|
|
18
|
-
const
|
|
15
|
+
const CONNECTION_REFERENCE = Symbol("managed-deepagents.connection");
|
|
19
16
|
const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
20
17
|
const MAX_SLUG_LENGTH = 64;
|
|
21
18
|
const DEFAULT_LANGSMITH_ENDPOINT = "https://api.smith.langchain.com";
|
|
22
19
|
const DEV_CREDENTIAL_PREFIX = "MDA_DEV_";
|
|
23
|
-
|
|
24
|
-
* A user-owned credential is an OAuth grant held per caller against the
|
|
25
|
-
* deployment, and `mda dev` has no deployment to hold one.
|
|
26
|
-
*/
|
|
27
|
-
function localUserCredentialUnsupported(slug) {
|
|
20
|
+
function localUserConnectionUnsupported(slug) {
|
|
28
21
|
const localHint = slug
|
|
29
|
-
? `set ${
|
|
22
|
+
? `set ${agentConnectionEnvKey(slug)}`
|
|
30
23
|
: "set the corresponding MDA_DEV_<slug> variable";
|
|
31
|
-
return ("user-
|
|
32
|
-
"deploy with `mda deploy` to exercise this
|
|
24
|
+
return ("user-owned connections need a deployment, so they do not resolve in `mda dev`: " +
|
|
25
|
+
"deploy with `mda deploy` to exercise this connection, or declare it as " +
|
|
33
26
|
`{ type: "agent" } and ${localHint} for local runs`);
|
|
34
27
|
}
|
|
35
|
-
|
|
36
|
-
const CREDENTIAL_KIND = { agent: "secret", user: "oauth2" };
|
|
37
|
-
export class CredentialNotFoundError extends Error {
|
|
28
|
+
export class ConnectionNotFoundError extends Error {
|
|
38
29
|
slug;
|
|
39
30
|
ownerType;
|
|
40
31
|
constructor(slug, ownerType) {
|
|
41
|
-
super(`no ${ownerType}
|
|
42
|
-
this.name = "
|
|
32
|
+
super(`no ${ownerType} connection is set for slug ${JSON.stringify(slug)}`);
|
|
33
|
+
this.name = "ConnectionNotFoundError";
|
|
43
34
|
this.slug = slug;
|
|
44
35
|
this.ownerType = ownerType;
|
|
45
36
|
}
|
|
46
37
|
}
|
|
47
|
-
|
|
48
|
-
* A declarative credential handle. Connector declarations inspect its owner;
|
|
49
|
-
* awaiting the same handle inside a tool resolves fresh material every time.
|
|
50
|
-
*/
|
|
51
|
-
export class CredentialReference {
|
|
38
|
+
export class ConnectionReference {
|
|
52
39
|
slug;
|
|
53
40
|
owner;
|
|
54
41
|
accessor;
|
|
55
|
-
[
|
|
42
|
+
[CONNECTION_REFERENCE] = true;
|
|
56
43
|
constructor(slug, owner, accessor) {
|
|
57
44
|
this.slug = slug;
|
|
58
45
|
this.owner = owner;
|
|
@@ -64,13 +51,13 @@ export class CredentialReference {
|
|
|
64
51
|
.then(onfulfilled, onrejected);
|
|
65
52
|
}
|
|
66
53
|
}
|
|
67
|
-
export function
|
|
68
|
-
return (value instanceof
|
|
54
|
+
export function isConnectionReference(value) {
|
|
55
|
+
return (value instanceof ConnectionReference ||
|
|
69
56
|
(typeof value === "object" &&
|
|
70
57
|
value !== null &&
|
|
71
|
-
|
|
58
|
+
CONNECTION_REFERENCE in value));
|
|
72
59
|
}
|
|
73
|
-
export class
|
|
60
|
+
export class AgentAuthConnectionStore {
|
|
74
61
|
env;
|
|
75
62
|
fetchImpl;
|
|
76
63
|
timeoutMs;
|
|
@@ -80,18 +67,16 @@ export class AgentAuthCredentialStore {
|
|
|
80
67
|
this.timeoutMs = timeoutMs;
|
|
81
68
|
}
|
|
82
69
|
async fetch(request) {
|
|
83
|
-
// `mda dev` has no deployment to resolve against, so local values stand in
|
|
84
|
-
// for agent secrets and a user grant has nothing to stand in for.
|
|
85
70
|
if (this.env.MDA_LOCAL_DEV === "1") {
|
|
86
71
|
if (request.owner.type === "user") {
|
|
87
|
-
throw new CredentialStoreError(
|
|
72
|
+
throw new CredentialStoreError(localUserConnectionUnsupported(request.slug));
|
|
88
73
|
}
|
|
89
|
-
const value = this.env[
|
|
74
|
+
const value = this.env[agentConnectionEnvKey(request.slug)];
|
|
90
75
|
if (value !== undefined && value.trim()) {
|
|
91
76
|
return value;
|
|
92
77
|
}
|
|
93
|
-
throw new CredentialStoreError(`local agent
|
|
94
|
-
`set ${
|
|
78
|
+
throw new CredentialStoreError(`local agent connection ${JSON.stringify(request.slug)} is not configured; ` +
|
|
79
|
+
`set ${agentConnectionEnvKey(request.slug)}`);
|
|
95
80
|
}
|
|
96
81
|
const config = resolveAgentAuthConfig(this.env);
|
|
97
82
|
const ownerId = resolveOwnerId(request.owner, request.identity, config.deploymentId);
|
|
@@ -102,32 +87,44 @@ export class AgentAuthCredentialStore {
|
|
|
102
87
|
apiKey: config.apiKey,
|
|
103
88
|
workspaceId: config.workspaceId,
|
|
104
89
|
}, this.fetchImpl, this.timeoutMs);
|
|
105
|
-
|
|
106
|
-
|
|
90
|
+
const row = await client.findWorkspaceConnection(request.slug);
|
|
91
|
+
if (!row) {
|
|
92
|
+
return undefined;
|
|
107
93
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
94
|
+
if (request.owner.type === "user") {
|
|
95
|
+
if (row.kind === "secret") {
|
|
96
|
+
return await client.readUserSecret(request.slug);
|
|
97
|
+
}
|
|
98
|
+
if (row.kind === "oauth2") {
|
|
99
|
+
return await client.readUserAccessToken(request.slug);
|
|
100
|
+
}
|
|
115
101
|
return undefined;
|
|
116
|
-
|
|
102
|
+
}
|
|
103
|
+
if (row.kind === "secret") {
|
|
104
|
+
const credentialId = await client.findWorkspaceCredentialId(request.slug);
|
|
105
|
+
if (!credentialId) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return await client.readSecret(credentialId);
|
|
109
|
+
}
|
|
110
|
+
if (row.kind === "oauth2") {
|
|
111
|
+
return await client.readConnectionAccessToken(row.connectionId);
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
117
114
|
}
|
|
118
115
|
}
|
|
119
|
-
export class
|
|
116
|
+
export class Connections {
|
|
120
117
|
store;
|
|
121
|
-
constructor(store = new
|
|
118
|
+
constructor(store = new AgentAuthConnectionStore()) {
|
|
122
119
|
this.store = store;
|
|
123
120
|
}
|
|
124
121
|
get(slug, owner) {
|
|
125
|
-
return new
|
|
122
|
+
return new ConnectionReference(normalizeSlug(slug), normalizeOwner(owner), this);
|
|
126
123
|
}
|
|
127
124
|
async resolve(slug, owner) {
|
|
128
125
|
const configurable = resolveRuntimeConfigurable(undefined);
|
|
129
126
|
if (!configurable) {
|
|
130
|
-
throw new Error("
|
|
127
|
+
throw new Error("connections.get(...) must be awaited inside a run: resolve a connection in a tool or middleware, not at import time");
|
|
131
128
|
}
|
|
132
129
|
const value = await this.store.fetch({
|
|
133
130
|
slug,
|
|
@@ -137,57 +134,49 @@ export class Credentials {
|
|
|
137
134
|
if (value === undefined) {
|
|
138
135
|
throw owner.type === "user"
|
|
139
136
|
? new CredentialAuthorizationRequiredError([slug])
|
|
140
|
-
: new
|
|
137
|
+
: new ConnectionNotFoundError(slug, owner.type);
|
|
141
138
|
}
|
|
142
139
|
return value;
|
|
143
140
|
}
|
|
144
|
-
/**
|
|
145
|
-
* Read an agent-owned secret outside a run.
|
|
146
|
-
*
|
|
147
|
-
* Connector declarations are loaded once per deployment, before any caller
|
|
148
|
-
* exists. An agent-owned secret is deployment-scoped, so it is the one lookup
|
|
149
|
-
* that carries no caller and can be resolved there.
|
|
150
|
-
*/
|
|
151
141
|
async resolveDeploymentSecret(slug) {
|
|
152
142
|
const value = await this.store.fetch({
|
|
153
143
|
slug,
|
|
154
144
|
owner: { type: "agent" },
|
|
155
145
|
});
|
|
156
146
|
if (value === undefined) {
|
|
157
|
-
throw new
|
|
147
|
+
throw new ConnectionNotFoundError(slug, "agent");
|
|
158
148
|
}
|
|
159
149
|
return value;
|
|
160
150
|
}
|
|
161
151
|
}
|
|
162
|
-
|
|
163
|
-
export function agentCredentialEnvKey(slug) {
|
|
152
|
+
export function agentConnectionEnvKey(slug) {
|
|
164
153
|
return `${DEV_CREDENTIAL_PREFIX}${normalizeSlug(slug)
|
|
165
154
|
.toUpperCase()
|
|
166
155
|
.replaceAll("-", "_")}`;
|
|
167
156
|
}
|
|
168
157
|
function normalizeSlug(slug) {
|
|
169
158
|
if (typeof slug !== "string") {
|
|
170
|
-
throw new TypeError("
|
|
159
|
+
throw new TypeError("connection slug must be a string");
|
|
171
160
|
}
|
|
172
161
|
const canonical = slug.trim();
|
|
173
162
|
if (!canonical ||
|
|
174
163
|
canonical.length > MAX_SLUG_LENGTH ||
|
|
175
164
|
!SLUG_PATTERN.test(canonical)) {
|
|
176
|
-
throw new TypeError(`
|
|
165
|
+
throw new TypeError(`connection slug ${JSON.stringify(slug)} is invalid: use lowercase letters, digits, and single hyphens, at most ${MAX_SLUG_LENGTH} characters`);
|
|
177
166
|
}
|
|
178
167
|
return canonical;
|
|
179
168
|
}
|
|
180
169
|
function normalizeOwner(owner) {
|
|
181
170
|
if (!owner || typeof owner !== "object") {
|
|
182
|
-
throw new TypeError('
|
|
171
|
+
throw new TypeError('connection owner is required: pass { type: "agent" } or { type: "user" }');
|
|
183
172
|
}
|
|
184
173
|
const keys = Object.keys(owner);
|
|
185
174
|
if (keys.some((key) => key !== "type" && key !== "id")) {
|
|
186
|
-
throw new TypeError("
|
|
175
|
+
throw new TypeError("connection owner has an unknown key");
|
|
187
176
|
}
|
|
188
177
|
if (owner.type === "agent") {
|
|
189
178
|
if ("id" in owner) {
|
|
190
|
-
throw new TypeError('
|
|
179
|
+
throw new TypeError('connection owner "id" is not accepted for { type: "agent" }');
|
|
191
180
|
}
|
|
192
181
|
return { type: "agent" };
|
|
193
182
|
}
|
|
@@ -195,48 +184,35 @@ function normalizeOwner(owner) {
|
|
|
195
184
|
if (owner.id === undefined)
|
|
196
185
|
return { type: "user" };
|
|
197
186
|
if (typeof owner.id !== "string" || !owner.id.trim()) {
|
|
198
|
-
throw new TypeError('
|
|
187
|
+
throw new TypeError('connection owner "id" must be a non-empty string');
|
|
199
188
|
}
|
|
200
189
|
return { type: "user", id: owner.id.trim() };
|
|
201
190
|
}
|
|
202
|
-
throw new TypeError("
|
|
191
|
+
throw new TypeError("connection owner type is not supported");
|
|
203
192
|
}
|
|
204
|
-
/**
|
|
205
|
-
* The `owner_id` a lookup is keyed by: the caller for a user, else the
|
|
206
|
-
* deployment. Shared with the credential gate so a declared owner is checked
|
|
207
|
-
* the same way wherever it is resolved.
|
|
208
|
-
*/
|
|
209
193
|
export function resolveOwnerId(owner, identity, deploymentId) {
|
|
210
194
|
if (owner.type === "user") {
|
|
211
195
|
const authenticated = identity?.user.id;
|
|
212
196
|
if (!authenticated) {
|
|
213
|
-
throw new CredentialStoreError("user
|
|
197
|
+
throw new CredentialStoreError("user connections require an authenticated user principal");
|
|
214
198
|
}
|
|
215
199
|
if (owner.id !== undefined && owner.id !== authenticated) {
|
|
216
|
-
throw new CredentialStoreError("user
|
|
200
|
+
throw new CredentialStoreError("user connection owner id must match the authenticated principal");
|
|
217
201
|
}
|
|
218
202
|
return authenticated;
|
|
219
203
|
}
|
|
220
204
|
if (!deploymentId) {
|
|
221
|
-
throw new CredentialStoreError("
|
|
205
|
+
throw new CredentialStoreError("connections are not configured: LANGSMITH_HOST_PROJECT_ID is not set");
|
|
222
206
|
}
|
|
223
207
|
return deploymentId;
|
|
224
208
|
}
|
|
225
|
-
/**
|
|
226
|
-
* The Agent Auth binding for one caller.
|
|
227
|
-
*
|
|
228
|
-
* `credentials.get` and the pre-run credential gate both resolve their owner id
|
|
229
|
-
* here, so a slug addresses the same Agent Auth row on either path.
|
|
230
|
-
*/
|
|
231
209
|
export function resolveAgentAuthContext(identity, env = process.env) {
|
|
232
|
-
// Only the user-credential gate resolves a context, so a local run can say
|
|
233
|
-
// why rather than reporting a missing deployment variable.
|
|
234
210
|
if (env.MDA_LOCAL_DEV === "1") {
|
|
235
|
-
throw new CredentialStoreError(
|
|
211
|
+
throw new CredentialStoreError(localUserConnectionUnsupported());
|
|
236
212
|
}
|
|
237
213
|
const config = resolveAgentAuthConfig(env);
|
|
238
214
|
if (!config.deploymentId) {
|
|
239
|
-
throw new CredentialStoreError("
|
|
215
|
+
throw new CredentialStoreError("connections are not configured: LANGSMITH_HOST_PROJECT_ID is not set");
|
|
240
216
|
}
|
|
241
217
|
return {
|
|
242
218
|
baseUrl: config.baseUrl,
|
|
@@ -249,21 +225,19 @@ export function resolveAgentAuthContext(identity, env = process.env) {
|
|
|
249
225
|
function resolveAgentAuthConfig(env) {
|
|
250
226
|
const apiKey = env.LANGSMITH_API_KEY?.trim();
|
|
251
227
|
if (!apiKey) {
|
|
252
|
-
throw new CredentialStoreError("
|
|
228
|
+
throw new CredentialStoreError("connections are not configured: LANGSMITH_API_KEY is not set");
|
|
229
|
+
}
|
|
230
|
+
const workspaceId = env.LANGSMITH_WORKSPACE_ID?.trim();
|
|
231
|
+
if (!workspaceId) {
|
|
232
|
+
throw new CredentialStoreError("connections are not configured: LANGSMITH_WORKSPACE_ID is not set");
|
|
253
233
|
}
|
|
254
234
|
return {
|
|
255
235
|
baseUrl: resolveAgentAuthBaseUrl(env),
|
|
256
236
|
apiKey,
|
|
257
237
|
deploymentId: env.LANGSMITH_HOST_PROJECT_ID?.trim() || undefined,
|
|
258
|
-
workspaceId
|
|
238
|
+
workspaceId,
|
|
259
239
|
};
|
|
260
240
|
}
|
|
261
|
-
/**
|
|
262
|
-
* Agent Auth is served by the LangSmith API.
|
|
263
|
-
*
|
|
264
|
-
* Rejects a URL that carries a path, query, or userinfo, so a misconfigured
|
|
265
|
-
* endpoint cannot send the API key at a different service.
|
|
266
|
-
*/
|
|
267
241
|
export function resolveAgentAuthBaseUrl(env = process.env) {
|
|
268
242
|
const raw = env.LANGSMITH_ENDPOINT?.trim() || DEFAULT_LANGSMITH_ENDPOINT;
|
|
269
243
|
let parsed;
|
|
@@ -284,5 +258,5 @@ export function resolveAgentAuthBaseUrl(env = process.env) {
|
|
|
284
258
|
}
|
|
285
259
|
return parsed.origin;
|
|
286
260
|
}
|
|
287
|
-
export const
|
|
288
|
-
//# sourceMappingURL=
|
|
261
|
+
export const connections = new Connections();
|
|
262
|
+
//# sourceMappingURL=connections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.js","sourceRoot":"","sources":["../src/connections.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* @example
|
|
19
19
|
* ```ts
|
|
20
20
|
* // connectors/mcp.ts
|
|
21
|
-
* import { connectors,
|
|
21
|
+
* import { connectors, connections } from "managed-deepagents";
|
|
22
22
|
*
|
|
23
23
|
* export const connector = connectors.mcp({
|
|
24
24
|
* mcpServers: {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* notion: {
|
|
30
30
|
* transport: "http",
|
|
31
31
|
* url: "https://mcp.notion.com/mcp",
|
|
32
|
-
*
|
|
32
|
+
* connection: connections.get("notion", { type: "user" }),
|
|
33
33
|
* },
|
|
34
34
|
* },
|
|
35
35
|
* });
|
|
@@ -51,17 +51,17 @@ export declare function clearManagedMcpToolsCacheForTests(connectors?: McpServer
|
|
|
51
51
|
/**
|
|
52
52
|
* The credential gate's view of the declared MCP connectors.
|
|
53
53
|
*
|
|
54
|
-
* One consumer per declaration that names a user-owned
|
|
54
|
+
* One consumer per declaration that names a user-owned connection; a
|
|
55
55
|
* declaration that needs no grant never reaches the gate.
|
|
56
56
|
*/
|
|
57
57
|
export declare function mcpCredentialConsumers(connectors: readonly unknown[] | undefined): CredentialConsumer[];
|
|
58
58
|
/**
|
|
59
|
-
* Load tools for user-
|
|
59
|
+
* Load tools for user-connection servers, once the gate has confirmed the
|
|
60
60
|
* caller's grants.
|
|
61
61
|
*
|
|
62
62
|
* Not process-cached here: the Authorization header is per caller, so the gate
|
|
63
63
|
* owns both the cache and closing the returned transport.
|
|
64
64
|
*/
|
|
65
|
-
export declare function
|
|
65
|
+
export declare function loadUserConnectionMcpTools(connectors: McpServersDefinition, accessTokens: ReadonlyMap<string, string>): Promise<LoadedCredentialTools>;
|
|
66
66
|
export declare const mcpConnector: (config: McpServersConfig) => McpServersDefinition;
|
|
67
67
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connectors/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAUH,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAEpB,mBAAmB,YAAY,CAAC;AAkBhC;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,OAAO,EAAE,CAAC,CAWpB;AAED,yDAAyD;AACzD,wBAAgB,iCAAiC,CAC/C,UAAU,CAAC,EAAE,oBAAoB,GAChC,IAAI,CAMN;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,GACzC,kBAAkB,EAAE,CAuBtB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connectors/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAUH,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAEpB,mBAAmB,YAAY,CAAC;AAkBhC;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,OAAO,EAAE,CAAC,CAWpB;AAED,yDAAyD;AACzD,wBAAgB,iCAAiC,CAC/C,UAAU,CAAC,EAAE,oBAAoB,GAChC,IAAI,CAMN;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,GACzC,kBAAkB,EAAE,CAuBtB;AA0ED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,oBAAoB,EAChC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,OAAO,CAAC,qBAAqB,CAAC,CAyBhC;AAsKD,eAAO,MAAM,YAAY,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,oBAOrD,CAAC"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* @example
|
|
19
19
|
* ```ts
|
|
20
20
|
* // connectors/mcp.ts
|
|
21
|
-
* import { connectors,
|
|
21
|
+
* import { connectors, connections } from "managed-deepagents";
|
|
22
22
|
*
|
|
23
23
|
* export const connector = connectors.mcp({
|
|
24
24
|
* mcpServers: {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* notion: {
|
|
30
30
|
* transport: "http",
|
|
31
31
|
* url: "https://mcp.notion.com/mcp",
|
|
32
|
-
*
|
|
32
|
+
* connection: connections.get("notion", { type: "user" }),
|
|
33
33
|
* },
|
|
34
34
|
* },
|
|
35
35
|
* });
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
*/
|
|
38
38
|
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
|
|
39
39
|
import { defineExtension } from "../../extension.js";
|
|
40
|
-
import {
|
|
40
|
+
import { connections, isConnectionReference, } from "../../connections.js";
|
|
41
41
|
import { mcpServersConfig } from "./schema.js";
|
|
42
42
|
import { selectTools } from "../tool-selection.js";
|
|
43
43
|
/**
|
|
@@ -50,8 +50,8 @@ import { selectTools } from "../tool-selection.js";
|
|
|
50
50
|
* the in-flight promise also dedupes concurrent first runs for the same
|
|
51
51
|
* connector. Multiple `connectors.mcp(...)` modules each get their own entry.
|
|
52
52
|
*
|
|
53
|
-
* An agent-owned
|
|
54
|
-
* secret takes a redeploy. Servers with a user-owned
|
|
53
|
+
* An agent-owned connection is read into this cache once, so rotating that
|
|
54
|
+
* secret takes a redeploy. Servers with a user-owned connection are omitted
|
|
55
55
|
* entirely; the credential gate loads those per caller.
|
|
56
56
|
*/
|
|
57
57
|
const cachedTools = new Map();
|
|
@@ -85,7 +85,7 @@ export function clearManagedMcpToolsCacheForTests(connectors) {
|
|
|
85
85
|
/**
|
|
86
86
|
* The credential gate's view of the declared MCP connectors.
|
|
87
87
|
*
|
|
88
|
-
* One consumer per declaration that names a user-owned
|
|
88
|
+
* One consumer per declaration that names a user-owned connection; a
|
|
89
89
|
* declaration that needs no grant never reaches the gate.
|
|
90
90
|
*/
|
|
91
91
|
export function mcpCredentialConsumers(connectors) {
|
|
@@ -97,72 +97,88 @@ export function mcpCredentialConsumers(connectors) {
|
|
|
97
97
|
continue;
|
|
98
98
|
}
|
|
99
99
|
const definition = connector;
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
100
|
+
const userConnections = userConnectionReferences(definition);
|
|
101
|
+
if (userConnections.length === 0) {
|
|
102
102
|
continue;
|
|
103
103
|
}
|
|
104
104
|
out.push({
|
|
105
105
|
declaration: definition,
|
|
106
|
-
credentials,
|
|
107
|
-
load: (accessTokens) =>
|
|
106
|
+
credentials: userConnections,
|
|
107
|
+
load: (accessTokens) => loadUserConnectionMcpTools(definition, accessTokens),
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
110
|
return out;
|
|
111
111
|
}
|
|
112
112
|
/** The declared references themselves: the gate checks their owner. */
|
|
113
|
-
function
|
|
113
|
+
function userConnectionReferences(connectors) {
|
|
114
114
|
const bySlug = new Map();
|
|
115
115
|
for (const server of Object.values(connectors.mcpServers)) {
|
|
116
|
-
if (
|
|
117
|
-
const
|
|
118
|
-
bySlug.set(
|
|
116
|
+
if (usesUserConnection(server)) {
|
|
117
|
+
const connection = server.connection;
|
|
118
|
+
bySlug.set(connection.slug, connection);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return [...bySlug.values()];
|
|
122
|
+
}
|
|
123
|
+
function agentConnectionReferences(connectors) {
|
|
124
|
+
const bySlug = new Map();
|
|
125
|
+
for (const server of Object.values(connectors.mcpServers)) {
|
|
126
|
+
const connection = server.connection;
|
|
127
|
+
if (isConnectionReference(connection) &&
|
|
128
|
+
connection.owner.type === "agent") {
|
|
129
|
+
bySlug.set(connection.slug, connection);
|
|
119
130
|
}
|
|
120
131
|
}
|
|
121
132
|
return [...bySlug.values()];
|
|
122
133
|
}
|
|
123
134
|
function mcpRequirements(name, connectors) {
|
|
135
|
+
const userSlugs = userConnectionReferences(connectors)
|
|
136
|
+
.map((connection) => connection.slug)
|
|
137
|
+
.sort();
|
|
138
|
+
const agentSlugs = agentConnectionReferences(connectors)
|
|
139
|
+
.map((connection) => connection.slug)
|
|
140
|
+
.sort();
|
|
124
141
|
return {
|
|
125
142
|
name,
|
|
126
143
|
provider: "mcp",
|
|
127
144
|
autoReply: false,
|
|
128
145
|
requiredPermissions: [],
|
|
129
146
|
requiredEnv: [],
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
.sort(),
|
|
147
|
+
userConnections: userSlugs,
|
|
148
|
+
agentConnections: agentSlugs,
|
|
133
149
|
providerConfig: {},
|
|
134
150
|
};
|
|
135
151
|
}
|
|
136
152
|
async function createClientAndLoadTools(connectors) {
|
|
137
|
-
const { eager,
|
|
138
|
-
if (
|
|
139
|
-
|
|
153
|
+
const { eager, userConnection } = partitionMcpServers(connectors.mcpServers);
|
|
154
|
+
if (userConnection.length > 0) {
|
|
155
|
+
warnDeferredUserConnectionServers(userConnection);
|
|
140
156
|
}
|
|
141
157
|
if (Object.keys(eager).length === 0) {
|
|
142
158
|
return [];
|
|
143
159
|
}
|
|
144
|
-
const { tools } = await loadToolsFromServers(connectors, await
|
|
160
|
+
const { tools } = await loadToolsFromServers(connectors, await withAgentConnections(eager));
|
|
145
161
|
return tools;
|
|
146
162
|
}
|
|
147
163
|
/**
|
|
148
|
-
* Load tools for user-
|
|
164
|
+
* Load tools for user-connection servers, once the gate has confirmed the
|
|
149
165
|
* caller's grants.
|
|
150
166
|
*
|
|
151
167
|
* Not process-cached here: the Authorization header is per caller, so the gate
|
|
152
168
|
* owns both the cache and closing the returned transport.
|
|
153
169
|
*/
|
|
154
|
-
export async function
|
|
155
|
-
const {
|
|
170
|
+
export async function loadUserConnectionMcpTools(connectors, accessTokens) {
|
|
171
|
+
const { userConnection } = partitionMcpServers(connectors.mcpServers);
|
|
156
172
|
const connectable = {};
|
|
157
|
-
for (const name of
|
|
173
|
+
for (const name of userConnection) {
|
|
158
174
|
const server = connectors.mcpServers[name];
|
|
159
|
-
const
|
|
160
|
-
if (!server || !
|
|
175
|
+
const connection = server?.connection;
|
|
176
|
+
if (!server || !isConnectionReference(connection)) {
|
|
161
177
|
continue;
|
|
162
178
|
}
|
|
163
|
-
const accessToken = accessTokens.get(
|
|
179
|
+
const accessToken = accessTokens.get(connection.slug);
|
|
164
180
|
if (!accessToken) {
|
|
165
|
-
throw new Error(`MCP user
|
|
181
|
+
throw new Error(`MCP user connection "${connection.slug}" has no access token`);
|
|
166
182
|
}
|
|
167
183
|
connectable[name] = withBearer(server, accessToken);
|
|
168
184
|
}
|
|
@@ -172,13 +188,13 @@ export async function loadUserCredentialMcpTools(connectors, accessTokens) {
|
|
|
172
188
|
const { tools, client } = await loadToolsFromServers(connectors, connectable);
|
|
173
189
|
return { tools, close: () => client.close() };
|
|
174
190
|
}
|
|
175
|
-
/** Resolve each agent-owned
|
|
176
|
-
async function
|
|
191
|
+
/** Resolve each agent-owned connection into a static bearer header. */
|
|
192
|
+
async function withAgentConnections(servers) {
|
|
177
193
|
const out = {};
|
|
178
194
|
for (const [name, server] of Object.entries(servers)) {
|
|
179
|
-
const
|
|
180
|
-
out[name] =
|
|
181
|
-
? withBearer(server, await
|
|
195
|
+
const connection = server.connection;
|
|
196
|
+
out[name] = isConnectionReference(connection)
|
|
197
|
+
? withBearer(server, await connections.resolveDeploymentSecret(connection.slug))
|
|
182
198
|
: server;
|
|
183
199
|
}
|
|
184
200
|
return out;
|
|
@@ -190,31 +206,31 @@ function withBearer(server, token) {
|
|
|
190
206
|
headers: { ...headers, Authorization: `Bearer ${token}` },
|
|
191
207
|
};
|
|
192
208
|
}
|
|
193
|
-
function
|
|
194
|
-
return (
|
|
195
|
-
server.
|
|
209
|
+
function usesUserConnection(server) {
|
|
210
|
+
return (isConnectionReference(server.connection) &&
|
|
211
|
+
server.connection.owner.type === "user");
|
|
196
212
|
}
|
|
197
213
|
function partitionMcpServers(servers) {
|
|
198
214
|
const eager = {};
|
|
199
|
-
const
|
|
215
|
+
const userConnection = [];
|
|
200
216
|
for (const [name, server] of Object.entries(servers)) {
|
|
201
|
-
if (
|
|
202
|
-
|
|
217
|
+
if (usesUserConnection(server)) {
|
|
218
|
+
userConnection.push(name);
|
|
203
219
|
}
|
|
204
220
|
else {
|
|
205
221
|
eager[name] = server;
|
|
206
222
|
}
|
|
207
223
|
}
|
|
208
|
-
return { eager,
|
|
224
|
+
return { eager, userConnection };
|
|
209
225
|
}
|
|
210
|
-
function
|
|
226
|
+
function warnDeferredUserConnectionServers(serverNames) {
|
|
211
227
|
console.warn(`[managed-deepagents] MCP server(s) ${serverNames.join(", ")} declare ` +
|
|
212
|
-
`a user
|
|
228
|
+
`a user connection; tools load after the pre-run credential gate ` +
|
|
213
229
|
`confirms grants for the caller.`);
|
|
214
230
|
}
|
|
215
231
|
function stripManagedToolSelection(servers) {
|
|
216
232
|
return Object.fromEntries(Object.entries(servers).map(([name, server]) => {
|
|
217
|
-
const { includeTools: _includeTools, excludeTools: _excludeTools,
|
|
233
|
+
const { includeTools: _includeTools, excludeTools: _excludeTools, connection: _connection, ...clientConfig } = server;
|
|
218
234
|
return [name, clientConfig];
|
|
219
235
|
}));
|
|
220
236
|
}
|