feat(tools): add live container tests and mark Task 3 complete in TODO.md

This commit is contained in:
Lucas Winther
2026-09-06 18:10:00 +02:00
parent 4eb17c2e5c
commit ebb47eb659
2 changed files with 90 additions and 9 deletions
+8 -8
View File
@@ -60,18 +60,18 @@
- [x] Implement `src/services/metadata.ts` (`listStatuses`, `listTypes`, `listPriorities`, `listUsers`).
- [x] Add service tests in `tests/services.test.ts` (unit tests and live container integration suite passing).
- [ ] **Task 3: MCP Tool Definitions & Schema Registration** *(In Progress: Tasks 1-3 of plan completed)*
- [ ] Define Zod schemas and register tools in `src/tools/`:
- [x] **Task 3: MCP Tool Definitions & Schema Registration**
- [x] Define Zod schemas and register tools in `src/tools/`:
- [x] `openproject_list_projects`
- [x] `openproject_get_project`
- [x] `openproject_list_work_packages`
- [x] `openproject_get_work_package`
- [ ] `openproject_list_queries`
- [ ] `openproject_get_query`
- [ ] `openproject_list_types`
- [ ] `openproject_list_statuses`
- [ ] `openproject_list_priorities`
- [ ] `openproject_list_users`
- [x] `openproject_list_queries`
- [x] `openproject_get_query`
- [x] `openproject_list_types`
- [x] `openproject_list_statuses`
- [x] `openproject_list_priorities`
- [x] `openproject_list_users`
- [ ] **Task 4: MCP Stdio Server Assembly & Integration**
- [ ] Wire domain tools into `@modelcontextprotocol/sdk` Server using `StdioServerTransport` in `src/server.ts` and `src/index.ts`.
+82 -1
View File
@@ -51,7 +51,7 @@ import { OpenProjectNotFoundError } from "../src/client/errors";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { runWithContext } from "../src/context";
import type { OpenProjectClient } from "../src/client/api-client";
import { OpenProjectClient } from "../src/client/api-client";
describe("Tool Utilities", () => {
@@ -989,5 +989,86 @@ describe("Tool Registry", () => {
});
});
describe("Live Container Integration (All 10 MCP Tools)", () => {
const baseUrl = process.env.OPENPROJECT_BASE_URL || "http://localhost:8080";
const apiKey = process.env.OPENPROJECT_API_KEY || "";
const liveClient = new OpenProjectClient({ baseUrl, apiKey });
test("live: list projects and get project tool execution", async () => {
await runWithContext({ client: liveClient, isReadOnly: false }, async () => {
const listRes = await handleListProjects({ pageSize: 5 });
expect(listRes.isError).toBeUndefined();
const listData = JSON.parse(listRes.content[0].text);
expect(listData.projects.length).toBeGreaterThan(0);
const targetProject =
listData.projects.find(
(p: { identifier?: string; id: number }) => p.identifier === "mcp-test-project"
) || listData.projects[0];
const getRes = await handleGetProject({ projectId: targetProject.id });
expect(getRes.isError).toBeUndefined();
const getData = JSON.parse(getRes.content[0].text);
expect(getData.id).toBe(targetProject.id);
});
});
test("live: list work packages and get work package tool execution", async () => {
await runWithContext({ client: liveClient, isReadOnly: false }, async () => {
const listRes = await handleListWorkPackages({ pageSize: 5 });
expect(listRes.isError).toBeUndefined();
const listData = JSON.parse(listRes.content[0].text);
expect(listData.workPackages.length).toBeGreaterThan(0);
const wpId = listData.workPackages[0].id;
const getRes = await handleGetWorkPackage({ workPackageId: wpId });
expect(getRes.isError).toBeUndefined();
const getData = JSON.parse(getRes.content[0].text);
expect(getData.id).toBe(wpId);
expect(getData.subject).toBeDefined();
});
});
test("live: list queries and get query tool execution", async () => {
await runWithContext({ client: liveClient, isReadOnly: false }, async () => {
const listRes = await handleListQueries({});
expect(listRes.isError).toBeUndefined();
const listData = JSON.parse(listRes.content[0].text);
expect(listData.queries.length).toBeGreaterThan(0);
const queryId = listData.queries[0].id;
const getRes = await handleGetQuery({ queryId });
expect(getRes.isError).toBeUndefined();
const getData = JSON.parse(getRes.content[0].text);
expect(getData.query.id).toBe(queryId);
expect(getData.results).toBeDefined();
});
});
test("live: metadata tools execution (types, statuses, priorities, users)", async () => {
await runWithContext({ client: liveClient, isReadOnly: false }, async () => {
const typesRes = await handleListTypes({});
expect(typesRes.isError).toBeUndefined();
const typesData = JSON.parse(typesRes.content[0].text);
expect(typesData.types.length).toBeGreaterThan(0);
const statusesRes = await handleListStatuses({});
expect(statusesRes.isError).toBeUndefined();
const statusesData = JSON.parse(statusesRes.content[0].text);
expect(statusesData.statuses.length).toBeGreaterThan(0);
const prioritiesRes = await handleListPriorities({});
expect(prioritiesRes.isError).toBeUndefined();
const prioritiesData = JSON.parse(prioritiesRes.content[0].text);
expect(prioritiesData.priorities.length).toBeGreaterThan(0);
const usersRes = await handleListUsers({ pageSize: 5 });
expect(usersRes.isError).toBeUndefined();
const usersData = JSON.parse(usersRes.content[0].text);
expect(usersData.users.length).toBeGreaterThan(0);
});
});
});