Skip to main content
Glama
integration.test.ts11.7 kB
import { describe, it, expect, beforeAll, afterAll } from "@jest/globals"; import { spawn, ChildProcess } from "child_process"; import { JrnlExecutor } from "../src/utils/jrnlExecutor"; describe("jrnl MCP Server Integration Tests", () => { let serverProcess: ChildProcess; let executor: JrnlExecutor; beforeAll(() => { executor = new JrnlExecutor(); }); describe("JrnlExecutor", () => { it("should execute jrnl commands", async () => { const result = await executor.execute(["--version"]); expect(result).toContain("jrnl"); }); }); describe("MCP Server", () => { beforeAll((done) => { serverProcess = spawn("node", ["dist/index.js"], { stdio: ["pipe", "pipe", "pipe"], }); serverProcess.stderr?.once("data", (data) => { if (data.toString().includes("jrnl MCP server started")) { done(); } }); }); afterAll(() => { if (serverProcess) { serverProcess.kill(); } }); it("should list available tools", (done) => { const request = { jsonrpc: "2.0", id: 1, method: "tools/list", params: {}, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.tools).toBeDefined(); expect(response.result.tools.length).toBe(6); const toolNames = response.result.tools.map((t: any) => t.name); expect(toolNames).toContain("search_entries"); expect(toolNames).toContain("list_tags"); expect(toolNames).toContain("analyze_tag_cooccurrence"); expect(toolNames).toContain("get_statistics"); expect(toolNames).toContain("list_journals"); expect(toolNames).toContain("set_journal"); done(); }); }); it("should handle call tool request for list_journals", (done) => { const request = { jsonrpc: "2.0", id: 2, method: "tools/call", params: { name: "list_journals", arguments: {}, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.journals).toBeDefined(); expect(Array.isArray(result.journals)).toBe(true); done(); }); }); describe("search_entries tool", () => { it("should search entries without filters", (done) => { const request = { jsonrpc: "2.0", id: 3, method: "tools/call", params: { name: "search_entries", arguments: {}, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.entries).toBeDefined(); expect(Array.isArray(result.entries)).toBe(true); expect(result.tags).toBeDefined(); done(); }); }); it("should search entries with date filters", (done) => { const request = { jsonrpc: "2.0", id: 4, method: "tools/call", params: { name: "search_entries", arguments: { from_date: "last week", to_date: "today", }, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.entries).toBeDefined(); expect(Array.isArray(result.entries)).toBe(true); expect(result.tags).toBeDefined(); done(); }); }); it("should search entries with tag filters", (done) => { const request = { jsonrpc: "2.0", id: 5, method: "tools/call", params: { name: "search_entries", arguments: { tags: ["@ciac"], }, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.entries).toBeDefined(); expect(Array.isArray(result.entries)).toBe(true); expect(result.tags).toBeDefined(); // Check that filtered entries only contain the requested tag if (result.entries.length > 0) { expect( result.entries.every( (entry: any) => entry.tags && entry.tags.includes("@ciac"), ), ).toBe(true); } done(); }); }); it("should search entries with multiple tag filters", (done) => { const request = { jsonrpc: "2.0", id: 6, method: "tools/call", params: { name: "search_entries", arguments: { tags: ["@ciac"], tag_mode: "and", }, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.entries).toBeDefined(); expect(Array.isArray(result.entries)).toBe(true); expect(result.tags).toBeDefined(); // Check that filtered entries only contain the requested tag if (result.entries.length > 0) { expect( result.entries.every( (entry: any) => entry.tags && entry.tags.includes("@ciac"), ), ).toBe(true); } done(); }); }); it("should search entries with text filter", (done) => { const request = { jsonrpc: "2.0", id: 7, method: "tools/call", params: { name: "search_entries", arguments: { text: "meeting", }, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.entries).toBeDefined(); expect(Array.isArray(result.entries)).toBe(true); expect(result.tags).toBeDefined(); done(); }); }); it("should search entries with combined filters", (done) => { const request = { jsonrpc: "2.0", id: 8, method: "tools/call", params: { name: "search_entries", arguments: { from_date: "last month", tags: ["@ciac"], text: "meeting", limit: 5, }, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.entries).toBeDefined(); expect(Array.isArray(result.entries)).toBe(true); expect(result.entries.length).toBeLessThanOrEqual(5); expect(result.tags).toBeDefined(); done(); }); }); }); describe("list_tags tool", () => { it("should list all tags", (done) => { const request = { jsonrpc: "2.0", id: 9, method: "tools/call", params: { name: "list_tags", arguments: {}, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.tags).toBeDefined(); expect(typeof result.tags).toBe("object"); expect(result.tags["@ciac"]).toBeGreaterThan(0); done(); }); }); }); describe("get_statistics tool", () => { it("should get journal statistics", (done) => { const request = { jsonrpc: "2.0", id: 10, method: "tools/call", params: { name: "get_statistics", arguments: {}, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.statistics).toBeDefined(); expect(result.statistics.totalEntries).toBeGreaterThanOrEqual(0); expect(result.statistics.totalWords).toBeGreaterThanOrEqual(0); expect(result.statistics.averageWordsPerEntry).toBeGreaterThanOrEqual( 0, ); done(); }); }); }); describe("analyze_tag_cooccurrence tool", () => { it("should analyze tag co-occurrence", (done) => { const request = { jsonrpc: "2.0", id: 11, method: "tools/call", params: { name: "analyze_tag_cooccurrence", arguments: {}, }, }; serverProcess.stdin?.write(JSON.stringify(request) + "\n"); serverProcess.stdout?.once("data", (data) => { const response = JSON.parse(data.toString().trim()); expect(response.result.content).toBeDefined(); expect(response.result.content[0].type).toBe("text"); const result = JSON.parse(response.result.content[0].text); expect(result.cooccurrences).toBeDefined(); expect(Array.isArray(result.cooccurrences)).toBe(true); done(); }); }); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yostos/jrnl-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server