feat(work-packages): add ranked search tool over subject, description, and comments

Registers openproject_search_work_packages (readOnly: true), taking the tool
registry from 18 to 19. searchWorkPackages now unions a precise server-side
subject filter with a broad recency-ordered candidate window, ranks via the
shared search pipeline, and deep-enriches top candidates with description and
comment text. Exact-mode requests skip the broad query entirely.

searchWorkPackages's return type changes from a flat PaginatedResult<WorkPackageSummary>
to WorkPackageSearchPage, nesting the summary under `workPackage` alongside
score, matchedFields, and an optional snippet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5 committed 2026-09-18 11:23:48 +02:00
1 parent 9dee458b1f
commit 326db0659f
7 files changed
+349 -29

No files matched your search

+3 -3
View File
@@ -74,7 +74,7 @@ describe("Read-Only Mode Enforcement", () => {
expect(configFalse.readOnly).toBe(false);
});
test("read-only server lists all 18 tools (all are readOnly: true)", async () => {
test("read-only server lists all 19 tools (all are readOnly: true)", async () => {
const mcpServer = createServer({
baseUrl: "http://localhost:8080",
apiKey: "test-key",
@@ -87,7 +87,7 @@ describe("Read-Only Mode Enforcement", () => {
await client.connect(clientTransport);
const toolsResult = await client.listTools();
expect(toolsResult.tools).toHaveLength(18);
expect(toolsResult.tools).toHaveLength(19);
await client.close();
await mcpServer.stop();
@@ -118,7 +118,7 @@ describe("Read-Only Mode Enforcement", () => {
const standaloneTools = await client2.listTools();
const standaloneNames = standaloneTools.tools.map((t) => t.name);
expect(standaloneNames).not.toContain("openproject_create_work_package_synthetic");
expect(standaloneTools.tools).toHaveLength(18);
expect(standaloneTools.tools).toHaveLength(19);
await client2.close();
await standaloneServer.close();