feat(tools): add tool registry and barrel export
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Model Context Protocol (MCP) Tools Registry and Barrel Export.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||||
|
import { registerTool, type ToolDefinition } from "./common";
|
||||||
|
import { projectTools } from "./projects";
|
||||||
|
import { workPackageTools } from "./work-packages";
|
||||||
|
import { queryTools } from "./queries";
|
||||||
|
import { metadataTools } from "./metadata";
|
||||||
|
|
||||||
|
export * from "./common";
|
||||||
|
export * from "./projects";
|
||||||
|
export * from "./work-packages";
|
||||||
|
export * from "./queries";
|
||||||
|
export * from "./metadata";
|
||||||
|
|
||||||
|
export type AnyToolDefinition =
|
||||||
|
| (typeof projectTools)[number]
|
||||||
|
| (typeof workPackageTools)[number]
|
||||||
|
| (typeof queryTools)[number]
|
||||||
|
| (typeof metadataTools)[number];
|
||||||
|
|
||||||
|
export const allTools: AnyToolDefinition[] = [
|
||||||
|
...projectTools,
|
||||||
|
...workPackageTools,
|
||||||
|
...queryTools,
|
||||||
|
...metadataTools,
|
||||||
|
];
|
||||||
|
|
||||||
|
export interface RegisterToolsOptions {
|
||||||
|
readOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all OpenProject tools with the given McpServer instance.
|
||||||
|
* If options.readOnly is true, tools not marked as readOnly are skipped.
|
||||||
|
*/
|
||||||
|
export function registerAllTools(
|
||||||
|
server: McpServer,
|
||||||
|
options?: RegisterToolsOptions
|
||||||
|
): void {
|
||||||
|
const isReadOnly = options?.readOnly ?? false;
|
||||||
|
|
||||||
|
for (const tool of allTools) {
|
||||||
|
// If server is in read-only mode, skip any non-read-only tools
|
||||||
|
if (isReadOnly && !tool.readOnly) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
registerTool(server, tool);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
import { describe, expect, test } from "bun:test";
|
import { describe, expect, test } from "bun:test";
|
||||||
|
import {
|
||||||
|
allTools,
|
||||||
|
registerAllTools,
|
||||||
|
type RegisterToolsOptions,
|
||||||
|
type AnyToolDefinition,
|
||||||
|
} from "../src/tools/index";
|
||||||
import {
|
import {
|
||||||
formatToolSuccess,
|
formatToolSuccess,
|
||||||
formatToolError,
|
formatToolError,
|
||||||
@@ -929,5 +935,59 @@ describe("Metadata Tools", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Tool Registry", () => {
|
||||||
|
test("allTools contains exactly 10 Phase 1 tools", () => {
|
||||||
|
expect(allTools).toHaveLength(10);
|
||||||
|
const names = allTools.map((t) => t.name);
|
||||||
|
expect(names).toEqual([
|
||||||
|
"openproject_list_projects",
|
||||||
|
"openproject_get_project",
|
||||||
|
"openproject_list_work_packages",
|
||||||
|
"openproject_get_work_package",
|
||||||
|
"openproject_list_queries",
|
||||||
|
"openproject_get_query",
|
||||||
|
"openproject_list_types",
|
||||||
|
"openproject_list_statuses",
|
||||||
|
"openproject_list_priorities",
|
||||||
|
"openproject_list_users",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("all tools in Phase 1 are marked readOnly: true", () => {
|
||||||
|
for (const tool of allTools) {
|
||||||
|
expect(tool.readOnly).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("registerAllTools registers all 10 tools on McpServer", () => {
|
||||||
|
const server = new McpServer({ name: "test-mcp", version: "1.0.0" });
|
||||||
|
registerAllTools(server);
|
||||||
|
|
||||||
|
const registeredTools = (
|
||||||
|
server as unknown as {
|
||||||
|
_registeredTools: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
)._registeredTools;
|
||||||
|
|
||||||
|
expect(Object.keys(registeredTools)).toHaveLength(10);
|
||||||
|
for (const tool of allTools) {
|
||||||
|
expect(registeredTools[tool.name]).toBeDefined();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("registerAllTools filters out non-readOnly tools when readOnly is true", () => {
|
||||||
|
const server = new McpServer({ name: "test-mcp", version: "1.0.0" });
|
||||||
|
registerAllTools(server, { readOnly: true });
|
||||||
|
|
||||||
|
const registeredTools = (
|
||||||
|
server as unknown as {
|
||||||
|
_registeredTools: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
)._registeredTools;
|
||||||
|
|
||||||
|
expect(Object.keys(registeredTools)).toHaveLength(10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user