@zvndev/circular-mcp 0.1.1 → 0.1.2
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/lib/server.mjs +1 -1
- package/lib/vendor/client.mjs +12 -3
- package/lib/vendor/config.mjs +6 -1
- package/package.json +1 -1
package/lib/server.mjs
CHANGED
|
@@ -21,7 +21,7 @@ const SUPPORTED_PROTOCOL_VERSIONS = new Set([
|
|
|
21
21
|
"2024-11-05",
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
|
-
export const SERVER_INFO = { name: "circular-mcp", version: "0.1.
|
|
24
|
+
export const SERVER_INFO = { name: "circular-mcp", version: "0.1.2" };
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* The briefing every client sees on connect. This is the only onboarding an
|
package/lib/vendor/client.mjs
CHANGED
|
@@ -99,11 +99,13 @@ export async function apiRequest(
|
|
|
99
99
|
|
|
100
100
|
let response = await send(config, method, url, body);
|
|
101
101
|
|
|
102
|
-
//
|
|
103
|
-
//
|
|
102
|
+
// Legacy unbound sessions get one retry when the file holds a different key.
|
|
103
|
+
// Bound sessions cannot prove that a global key represents the same agent
|
|
104
|
+
// and human, so they must reconnect instead of silently changing identity.
|
|
105
|
+
// The config object is mutated so the session uses the live key afterward:
|
|
104
106
|
// recovering one request and leaving the next twenty to fail would be worse
|
|
105
107
|
// than not recovering at all, because the failure would look intermittent.
|
|
106
|
-
if (response.status === 401) {
|
|
108
|
+
if (response.status === 401 && !config.agentParticipantId) {
|
|
107
109
|
const rotated = rotatedKey(config.apiKey, readFile);
|
|
108
110
|
if (rotated) {
|
|
109
111
|
config.apiKey = rotated;
|
|
@@ -120,6 +122,13 @@ export async function apiRequest(
|
|
|
120
122
|
}
|
|
121
123
|
|
|
122
124
|
if (!response.ok) {
|
|
125
|
+
if (response.status === 401 && config.agentParticipantId) {
|
|
126
|
+
throw new ApiError(
|
|
127
|
+
`${method} ${path} failed (401): This agent session credential expired or was revoked. Reconnect the session in Circular to authorize the same agent again; the global account key was not used.`,
|
|
128
|
+
response.status,
|
|
129
|
+
parsed,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
123
132
|
const detail =
|
|
124
133
|
parsed && typeof parsed === "object" && parsed.error ? parsed.error : response.statusText;
|
|
125
134
|
throw new ApiError(`${method} ${path} failed (${response.status}): ${detail}`, response.status, parsed);
|
package/lib/vendor/config.mjs
CHANGED
|
@@ -42,20 +42,25 @@ export function readConfigFile(path = configFilePath()) {
|
|
|
42
42
|
* CLI flags; `env` defaults to process.env; `file` is the parsed config file.
|
|
43
43
|
*/
|
|
44
44
|
export function resolveConfig(flags = {}, env = process.env, file = {}) {
|
|
45
|
+
const agentParticipantId = env.CIRCULAR_AGENT_PARTICIPANT_ID?.trim();
|
|
46
|
+
const authorizingUserId = env.CIRCULAR_AUTHORIZING_USER_ID?.trim();
|
|
45
47
|
const pick = (flagKey, envKey, fileKey, fallback) => {
|
|
46
48
|
if (flags[flagKey] !== undefined && flags[flagKey] !== true) return flags[flagKey];
|
|
47
49
|
if (env[envKey]) return env[envKey];
|
|
48
|
-
if (file[fileKey]) return file[fileKey];
|
|
50
|
+
if (file[fileKey] && !(agentParticipantId && fileKey === "apiKey")) return file[fileKey];
|
|
49
51
|
return fallback;
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
return {
|
|
55
|
+
// A bound session cannot borrow the operator's global credential, including
|
|
56
|
+
// when its delegated key is missing rather than rejected by the server.
|
|
53
57
|
apiKey: pick("api-key", "CIRCULAR_API_KEY", "apiKey", undefined),
|
|
54
58
|
baseUrl: stripTrailingSlash(
|
|
55
59
|
pick("base-url", "CIRCULAR_BASE_URL", "baseUrl", DEFAULT_BASE_URL)
|
|
56
60
|
),
|
|
57
61
|
workspaceId: pick("workspace", "CIRCULAR_WORKSPACE_ID", "workspaceId", undefined),
|
|
58
62
|
teamId: pick("team", "CIRCULAR_TEAM_ID", "teamId", undefined),
|
|
63
|
+
...(agentParticipantId ? { agentParticipantId, ...(authorizingUserId ? { authorizingUserId } : {}) } : {}),
|
|
59
64
|
};
|
|
60
65
|
}
|
|
61
66
|
|
package/package.json
CHANGED