@anyproto/anytype-mcp 1.0.2 → 1.0.3

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.
@@ -0,0 +1,205 @@
1
+ import axios from "axios";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { loadOpenApiSpec, ValidationError } from "../../src/init-server";
6
+
7
+ // Mock fs and axios
8
+ vi.mock("node:fs");
9
+ vi.mock("axios");
10
+ vi.mock("@modelcontextprotocol/sdk/server/stdio.js");
11
+
12
+ // Create a mock Server class with proper prototype methods
13
+ const mockSetRequestHandler = vi.fn();
14
+ const mockConnect = vi.fn();
15
+
16
+ function createMockServer(info: any, options: any) {
17
+ const server = {
18
+ info,
19
+ options,
20
+ };
21
+
22
+ Object.defineProperty(server, "setRequestHandler", {
23
+ value: mockSetRequestHandler,
24
+ writable: false,
25
+ configurable: true,
26
+ });
27
+
28
+ Object.defineProperty(server, "connect", {
29
+ value: mockConnect,
30
+ writable: false,
31
+ configurable: true,
32
+ });
33
+
34
+ return server;
35
+ }
36
+
37
+ vi.mock("@modelcontextprotocol/sdk/server/index.js", () => ({
38
+ Server: vi.fn().mockImplementation((info, options) => createMockServer(info, options)),
39
+ }));
40
+
41
+ const validOpenApiSpec = {
42
+ openapi: "3.1.0",
43
+ info: {
44
+ title: "Test API",
45
+ version: "1.0.0",
46
+ },
47
+ servers: [{ url: "http://localhost:3000" }],
48
+ paths: {
49
+ "/pets": {
50
+ get: {
51
+ operationId: "getPets",
52
+ responses: {
53
+ "200": { description: "A list of pets" },
54
+ },
55
+ },
56
+ },
57
+ },
58
+ };
59
+
60
+ describe("loadOpenApiSpec", () => {
61
+ beforeEach(() => {
62
+ vi.clearAllMocks();
63
+ // Reset console.error to capture output
64
+ vi.spyOn(console, "error").mockImplementation(() => {});
65
+ });
66
+
67
+ afterEach(() => {
68
+ vi.resetAllMocks();
69
+ });
70
+
71
+ describe("Local file loading", () => {
72
+ it("should load a valid OpenAPI spec from local file", async () => {
73
+ // Mock fs.readFileSync to return a valid spec
74
+ vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify(validOpenApiSpec));
75
+
76
+ const result = await loadOpenApiSpec("./test-spec.json");
77
+
78
+ expect(result).toEqual(validOpenApiSpec);
79
+ expect(fs.readFileSync).toHaveBeenCalledWith(path.resolve(process.cwd(), "./test-spec.json"), "utf-8");
80
+ });
81
+
82
+ it("should handle file not found error", async () => {
83
+ // Mock fs.readFileSync to throw ENOENT
84
+ vi.mocked(fs.readFileSync).mockImplementation(() => {
85
+ throw new Error("ENOENT: no such file or directory");
86
+ });
87
+
88
+ // Mock process.exit to prevent actual exit
89
+ const mockExit = vi.spyOn(process, "exit").mockImplementation((() => {}) as any);
90
+
91
+ await loadOpenApiSpec("./non-existent.json");
92
+
93
+ expect(console.error).toHaveBeenCalledWith("Failed to read OpenAPI specification file:", expect.any(String));
94
+ expect(mockExit).toHaveBeenCalledWith(1);
95
+ });
96
+
97
+ it("should handle invalid JSON", async () => {
98
+ // Mock fs.readFileSync to return invalid JSON
99
+ vi.mocked(fs.readFileSync).mockReturnValue("invalid json");
100
+
101
+ // Mock process.exit
102
+ const mockExit = vi.spyOn(process, "exit").mockImplementation((() => {}) as any);
103
+
104
+ await loadOpenApiSpec("./invalid.json");
105
+
106
+ expect(console.error).toHaveBeenCalledWith("Failed to parse OpenAPI specification:", expect.any(String));
107
+ expect(mockExit).toHaveBeenCalledWith(1);
108
+ });
109
+
110
+ it("should load a valid OpenAPI spec from local YAML file", async () => {
111
+ // Mock fs.readFileSync to return a valid YAML spec
112
+ const yamlSpec = JSON.stringify(validOpenApiSpec);
113
+ vi.mocked(fs.readFileSync).mockReturnValue(yamlSpec);
114
+
115
+ const result = await loadOpenApiSpec("./test-spec.yaml");
116
+
117
+ expect(result).toEqual(validOpenApiSpec);
118
+ expect(fs.readFileSync).toHaveBeenCalledWith(path.resolve(process.cwd(), "./test-spec.yaml"), "utf-8");
119
+ });
120
+
121
+ it("should handle invalid YAML", async () => {
122
+ // Mock fs.readFileSync to return invalid YAML
123
+ vi.mocked(fs.readFileSync).mockReturnValue("invalid: yaml: :");
124
+
125
+ // Mock process.exit
126
+ const mockExit = vi.spyOn(process, "exit").mockImplementation((() => {}) as any);
127
+
128
+ await loadOpenApiSpec("./invalid.yaml");
129
+
130
+ expect(console.error).toHaveBeenCalledWith("Failed to parse OpenAPI specification:", expect.any(String));
131
+ expect(mockExit).toHaveBeenCalledWith(1);
132
+ });
133
+ });
134
+
135
+ describe("URL loading", () => {
136
+ it("should load a valid OpenAPI spec from URL", async () => {
137
+ // Mock axios.get to return a valid spec
138
+ vi.mocked(axios.get).mockResolvedValue({ data: validOpenApiSpec });
139
+
140
+ const result = await loadOpenApiSpec("http://example.com/api-spec.json");
141
+
142
+ expect(result).toEqual(validOpenApiSpec);
143
+ expect(axios.get).toHaveBeenCalledWith("http://example.com/api-spec.json");
144
+ });
145
+
146
+ it("should handle network errors", async () => {
147
+ // Mock axios.get to throw network error
148
+ vi.mocked(axios.get).mockRejectedValue(new Error("Network Error"));
149
+
150
+ // Mock process.exit
151
+ const mockExit = vi.spyOn(process, "exit").mockImplementation((() => {}) as any);
152
+
153
+ await loadOpenApiSpec("http://example.com/api-spec.json");
154
+
155
+ expect(console.error).toHaveBeenCalledWith("Failed to fetch OpenAPI specification from URL:", "Network Error");
156
+ expect(mockExit).toHaveBeenCalledWith(1);
157
+ });
158
+
159
+ it("should handle invalid response data", async () => {
160
+ // Mock axios.get to return invalid data
161
+ vi.mocked(axios.get).mockResolvedValue({ data: "invalid data" });
162
+
163
+ // Mock process.exit
164
+ const mockExit = vi.spyOn(process, "exit").mockImplementation((() => {}) as any);
165
+
166
+ await loadOpenApiSpec("http://example.com/api-spec.json");
167
+
168
+ expect(console.error).toHaveBeenCalledWith("Failed to parse OpenAPI specification:", expect.any(String));
169
+ expect(mockExit).toHaveBeenCalledWith(1);
170
+ });
171
+
172
+ it("should load a valid OpenAPI spec from YAML URL", async () => {
173
+ // Mock axios.get to return a valid YAML spec
174
+ const yamlSpec = JSON.stringify(validOpenApiSpec);
175
+ vi.mocked(axios.get).mockResolvedValue({ data: yamlSpec });
176
+
177
+ const result = await loadOpenApiSpec("http://example.com/api-spec.yaml");
178
+
179
+ expect(result).toEqual(validOpenApiSpec);
180
+ expect(axios.get).toHaveBeenCalledWith("http://example.com/api-spec.yaml");
181
+ });
182
+ });
183
+ });
184
+
185
+ describe("main", () => {
186
+ beforeEach(() => {
187
+ vi.clearAllMocks();
188
+ vi.spyOn(console, "error").mockImplementation(() => {});
189
+ });
190
+
191
+ afterEach(() => {
192
+ vi.resetAllMocks();
193
+ });
194
+ });
195
+
196
+ describe("ValidationError", () => {
197
+ it("should create error with validation details", () => {
198
+ const errors = [{ message: "Missing required field" }];
199
+ const error = new ValidationError(errors);
200
+
201
+ expect(error.name).toBe("ValidationError");
202
+ expect(error.message).toBe("OpenAPI validation failed");
203
+ expect(error.errors).toEqual(errors);
204
+ });
205
+ });
@@ -0,0 +1,30 @@
1
+ import * as esbuild from "esbuild";
2
+ import { chmod } from "fs/promises";
3
+ import { dirname, join } from "path";
4
+ import { fileURLToPath } from "url";
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+
8
+ async function build() {
9
+ await esbuild.build({
10
+ entryPoints: [join(__dirname, "start-server.ts")],
11
+ bundle: true,
12
+ minify: true,
13
+ platform: "node",
14
+ target: "node18",
15
+ format: "esm",
16
+ outfile: "bin/cli.mjs",
17
+ banner: {
18
+ js: "#!/usr/bin/env node\nimport { createRequire } from 'module';const require = createRequire(import.meta.url);", // see https://github.com/evanw/esbuild/pull/2067
19
+ },
20
+ external: ["util"],
21
+ });
22
+
23
+ // Make the output file executable
24
+ await chmod("./bin/cli.mjs", 0o755);
25
+ }
26
+
27
+ build().catch((err) => {
28
+ console.error(err);
29
+ process.exit(1);
30
+ });
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { build } from "esbuild";
4
+
5
+ async function main() {
6
+ try {
7
+ await build({
8
+ entryPoints: ["src/index.ts"],
9
+ bundle: true,
10
+ platform: "node",
11
+ target: "node18",
12
+ format: "esm",
13
+ outfile: "dist/index.js",
14
+ sourcemap: true,
15
+ external: ["@modelcontextprotocol/sdk", "openapi-types"],
16
+ });
17
+ console.log("Build completed successfully");
18
+ } catch (error) {
19
+ console.error("Build failed:", error);
20
+ process.exit(1);
21
+ }
22
+ }
23
+
24
+ main();