@loopops/mcp-server 2.0.0 → 2.0.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/dist/api-client.js +36 -22
- package/package.json +1 -1
package/dist/api-client.js
CHANGED
|
@@ -153,34 +153,48 @@ function isRetryable(err) {
|
|
|
153
153
|
return false;
|
|
154
154
|
}
|
|
155
155
|
/**
|
|
156
|
-
* Persist a rotated refresh token
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
156
|
+
* Persist a rotated refresh token across every config location we know
|
|
157
|
+
* users store MCP settings in:
|
|
158
|
+
* - ~/.mcp.json (Claude Desktop)
|
|
159
|
+
* - ~/.claude/settings.json (Claude Code)
|
|
160
|
+
*
|
|
161
|
+
* We update whichever files have the loop-operations stanza. Missing
|
|
162
|
+
* files are skipped silently. This mirrors @loopops/mcp-cli's
|
|
163
|
+
* `updateRefreshToken` helper — keep the two in sync.
|
|
164
|
+
*
|
|
165
|
+
* Best-effort: if all writes fail, we still keep the new token
|
|
166
|
+
* in-memory so the current subprocess keeps working. The next cold
|
|
167
|
+
* spawn is the one that breaks.
|
|
160
168
|
*/
|
|
161
169
|
function persistRotatedRefreshToken(newToken) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const data = JSON.parse(raw);
|
|
168
|
-
const stanza = data.mcpServers?.[SERVER_NAME];
|
|
169
|
-
if (!stanza?.env)
|
|
170
|
-
return;
|
|
171
|
-
stanza.env.OKTA_REFRESH_TOKEN = newToken;
|
|
172
|
-
writeFileSync(path, JSON.stringify(data, null, 2) + "\n");
|
|
170
|
+
const paths = [
|
|
171
|
+
join(homedir(), ".mcp.json"),
|
|
172
|
+
join(homedir(), ".claude", "settings.json"),
|
|
173
|
+
];
|
|
174
|
+
for (const path of paths) {
|
|
173
175
|
try {
|
|
174
|
-
|
|
176
|
+
if (!existsSync(path))
|
|
177
|
+
continue;
|
|
178
|
+
const raw = readFileSync(path, "utf-8");
|
|
179
|
+
const data = JSON.parse(raw);
|
|
180
|
+
const stanza = data.mcpServers?.[SERVER_NAME];
|
|
181
|
+
if (!stanza?.env)
|
|
182
|
+
continue;
|
|
183
|
+
stanza.env.OKTA_REFRESH_TOKEN = newToken;
|
|
184
|
+
writeFileSync(path, JSON.stringify(data, null, 2) + "\n");
|
|
185
|
+
try {
|
|
186
|
+
chmodSync(path, 0o600);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// ok on platforms where this is a no-op
|
|
190
|
+
}
|
|
175
191
|
}
|
|
176
|
-
catch {
|
|
177
|
-
//
|
|
192
|
+
catch (err) {
|
|
193
|
+
// Log to stderr (visible in Claude Desktop/Code logs) but don't
|
|
194
|
+
// fail the request.
|
|
195
|
+
console.error(`[MCP] Could not persist rotated refresh token to ${path}:`, err instanceof Error ? err.message : String(err));
|
|
178
196
|
}
|
|
179
197
|
}
|
|
180
|
-
catch (err) {
|
|
181
|
-
// Log to stderr (visible in Claude Desktop logs) but don't fail the request.
|
|
182
|
-
console.error("[MCP] Could not persist rotated refresh token to ~/.mcp.json:", err instanceof Error ? err.message : String(err));
|
|
183
|
-
}
|
|
184
198
|
}
|
|
185
199
|
/**
|
|
186
200
|
* Mint a fresh access token via Okta's /token endpoint. Updates the
|