@crush-protocol/mcp-client 0.4.3 → 0.4.5
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/INSTRUCTIONS.md +16 -0
- package/README.md +46 -659
- package/dist/cli.js +6 -0
- package/dist/mcp/authPreflight.d.ts +9 -0
- package/dist/mcp/authPreflight.js +26 -0
- package/dist/mcp/oauthProvider.d.ts +2 -0
- package/dist/mcp/oauthProvider.js +8 -1
- package/dist/mcp/oauthRemoteClient.d.ts +3 -0
- package/dist/mcp/oauthRemoteClient.js +31 -18
- package/dist/mcp/proxy.js +29 -114
- package/dist/onboarding/cliOutput.d.ts +2 -0
- package/dist/onboarding/cliOutput.js +15 -0
- package/package.json +68 -46
- package/LICENSE +0 -21
- package/dist/__tests__/cliOutput.test.d.ts +0 -1
- package/dist/__tests__/cliOutput.test.js +0 -34
- package/dist/__tests__/e2e.test.d.ts +0 -1
- package/dist/__tests__/e2e.test.js +0 -50
- package/dist/__tests__/oauthProvider.test.d.ts +0 -1
- package/dist/__tests__/oauthProvider.test.js +0 -45
- package/dist/__tests__/oauthStorage.test.d.ts +0 -1
- package/dist/__tests__/oauthStorage.test.js +0 -52
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { mkdtemp, readFile } from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
-
import { InteractiveOAuthProvider } from "../mcp/oauthProvider.js";
|
|
6
|
-
const tempDirs = [];
|
|
7
|
-
const createProvider = async () => {
|
|
8
|
-
const storageDir = await mkdtemp(path.join(os.tmpdir(), "crush-mcp-oauth-"));
|
|
9
|
-
tempDirs.push(storageDir);
|
|
10
|
-
const provider = new InteractiveOAuthProvider({
|
|
11
|
-
serverUrl: "https://example.com/mcp",
|
|
12
|
-
storageDir,
|
|
13
|
-
openBrowser: false,
|
|
14
|
-
});
|
|
15
|
-
return { provider, storageDir };
|
|
16
|
-
};
|
|
17
|
-
describe("InteractiveOAuthProvider", () => {
|
|
18
|
-
afterEach(async () => {
|
|
19
|
-
await Promise.all(tempDirs
|
|
20
|
-
.splice(0)
|
|
21
|
-
.map((dir) => import("node:fs/promises").then((fs) => fs.rm(dir, { recursive: true, force: true }))));
|
|
22
|
-
});
|
|
23
|
-
it("persists client info, tokens, and code verifier", async () => {
|
|
24
|
-
const { provider, storageDir } = await createProvider();
|
|
25
|
-
await provider.saveClientInformation({ client_id: "client_123" });
|
|
26
|
-
await provider.saveTokens({ access_token: "atk_123", token_type: "Bearer", refresh_token: "rt_123" });
|
|
27
|
-
await provider.saveCodeVerifier("verifier-123");
|
|
28
|
-
expect(await provider.clientInformation()).toEqual({ client_id: "client_123" });
|
|
29
|
-
expect(await provider.tokens()).toEqual({ access_token: "atk_123", token_type: "Bearer", refresh_token: "rt_123" });
|
|
30
|
-
expect(await provider.codeVerifier()).toBe("verifier-123");
|
|
31
|
-
const files = await import("node:fs/promises").then((fs) => fs.readdir(storageDir));
|
|
32
|
-
expect(files.length).toBe(1);
|
|
33
|
-
const raw = await readFile(path.join(storageDir, files[0]), "utf8");
|
|
34
|
-
expect(raw).toContain("client_123");
|
|
35
|
-
expect(raw).toContain("atk_123");
|
|
36
|
-
});
|
|
37
|
-
it("invalidates token state without removing client registration", async () => {
|
|
38
|
-
const { provider } = await createProvider();
|
|
39
|
-
await provider.saveClientInformation({ client_id: "client_123" });
|
|
40
|
-
await provider.saveTokens({ access_token: "atk_123", token_type: "Bearer", refresh_token: "rt_123" });
|
|
41
|
-
await provider.invalidateCredentials?.("tokens");
|
|
42
|
-
expect(await provider.clientInformation()).toEqual({ client_id: "client_123" });
|
|
43
|
-
expect(await provider.tokens()).toBeUndefined();
|
|
44
|
-
});
|
|
45
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { mkdtemp, writeFile } from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
-
import { defaultStorageDir, getCachedAuthStatus, getStorageFileForServer, loadStoredTokens, } from "../mcp/oauthStorage.js";
|
|
6
|
-
const tempDirs = [];
|
|
7
|
-
describe("oauthStorage", () => {
|
|
8
|
-
afterEach(async () => {
|
|
9
|
-
await Promise.all(tempDirs
|
|
10
|
-
.splice(0)
|
|
11
|
-
.map((dir) => import("node:fs/promises").then((fs) => fs.rm(dir, { recursive: true, force: true }))));
|
|
12
|
-
});
|
|
13
|
-
it("reports authenticated state when tokens are present", async () => {
|
|
14
|
-
const storageDir = await mkdtemp(path.join(os.tmpdir(), "crush-mcp-storage-"));
|
|
15
|
-
tempDirs.push(storageDir);
|
|
16
|
-
const storageFile = getStorageFileForServer("https://example.com/mcp", storageDir);
|
|
17
|
-
await writeFile(storageFile, JSON.stringify({
|
|
18
|
-
clientInformation: { client_id: "client_123" },
|
|
19
|
-
tokens: { access_token: "atk_123", refresh_token: "rt_123", token_type: "Bearer", scope: "mcp:tools" },
|
|
20
|
-
}), "utf8");
|
|
21
|
-
const status = await getCachedAuthStatus("https://example.com/mcp", storageDir);
|
|
22
|
-
expect(status.status).toBe("authenticated");
|
|
23
|
-
expect(status.hasRefreshToken).toBe(true);
|
|
24
|
-
expect(status.storageFile).toBe(storageFile);
|
|
25
|
-
});
|
|
26
|
-
it("falls back between /mcp and base URL variants", async () => {
|
|
27
|
-
const storageDir = await mkdtemp(path.join(os.tmpdir(), "crush-mcp-storage-"));
|
|
28
|
-
tempDirs.push(storageDir);
|
|
29
|
-
const storageFile = getStorageFileForServer("https://example.com", storageDir);
|
|
30
|
-
await writeFile(storageFile, JSON.stringify({
|
|
31
|
-
clientInformation: { client_id: "client_123" },
|
|
32
|
-
tokens: { access_token: "atk_123", token_type: "Bearer" },
|
|
33
|
-
}), "utf8");
|
|
34
|
-
const tokens = await loadStoredTokens("https://example.com/mcp", storageDir);
|
|
35
|
-
expect(tokens?.access_token).toBe("atk_123");
|
|
36
|
-
});
|
|
37
|
-
it("reports registered state when only client metadata exists", async () => {
|
|
38
|
-
const storageDir = await mkdtemp(path.join(os.tmpdir(), "crush-mcp-storage-"));
|
|
39
|
-
tempDirs.push(storageDir);
|
|
40
|
-
const storageFile = getStorageFileForServer("https://example.com/mcp", storageDir);
|
|
41
|
-
await writeFile(storageFile, JSON.stringify({
|
|
42
|
-
clientInformation: { client_id: "client_123" },
|
|
43
|
-
codeVerifier: "verifier_123",
|
|
44
|
-
}), "utf8");
|
|
45
|
-
const status = await getCachedAuthStatus("https://example.com/mcp", storageDir);
|
|
46
|
-
expect(status.status).toBe("registered");
|
|
47
|
-
expect(status.hasCodeVerifier).toBe(true);
|
|
48
|
-
});
|
|
49
|
-
it("uses the default storage directory helper", () => {
|
|
50
|
-
expect(defaultStorageDir()).toContain(".crush-mcp");
|
|
51
|
-
});
|
|
52
|
-
});
|