castor-mcp 0.6.0

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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/build/api-catalog.d.ts +27 -0
  4. package/build/api-catalog.js +76 -0
  5. package/build/api-catalog.js.map +1 -0
  6. package/build/confluence-client.d.ts +33 -0
  7. package/build/confluence-client.js +65 -0
  8. package/build/confluence-client.js.map +1 -0
  9. package/build/index.d.ts +2 -0
  10. package/build/index.js +137 -0
  11. package/build/index.js.map +1 -0
  12. package/build/resource-definitions.d.ts +10 -0
  13. package/build/resource-definitions.js +75 -0
  14. package/build/resource-definitions.js.map +1 -0
  15. package/build/tool-definitions.d.ts +19 -0
  16. package/build/tool-definitions.js +1811 -0
  17. package/build/tool-definitions.js.map +1 -0
  18. package/build/tools/admin-users-groups.d.ts +114 -0
  19. package/build/tools/admin-users-groups.js +150 -0
  20. package/build/tools/admin-users-groups.js.map +1 -0
  21. package/build/tools/admin.d.ts +12 -0
  22. package/build/tools/admin.js +30 -0
  23. package/build/tools/admin.js.map +1 -0
  24. package/build/tools/args.d.ts +2 -0
  25. package/build/tools/args.js +12 -0
  26. package/build/tools/args.js.map +1 -0
  27. package/build/tools/attachments.d.ts +138 -0
  28. package/build/tools/attachments.js +170 -0
  29. package/build/tools/attachments.js.map +1 -0
  30. package/build/tools/backup-restore.d.ts +144 -0
  31. package/build/tools/backup-restore.js +223 -0
  32. package/build/tools/backup-restore.js.map +1 -0
  33. package/build/tools/bulk-pages.d.ts +103 -0
  34. package/build/tools/bulk-pages.js +111 -0
  35. package/build/tools/bulk-pages.js.map +1 -0
  36. package/build/tools/color-schemes.d.ts +72 -0
  37. package/build/tools/color-schemes.js +121 -0
  38. package/build/tools/color-schemes.js.map +1 -0
  39. package/build/tools/content-structure.d.ts +164 -0
  40. package/build/tools/content-structure.js +220 -0
  41. package/build/tools/content-structure.js.map +1 -0
  42. package/build/tools/content.d.ts +194 -0
  43. package/build/tools/content.js +246 -0
  44. package/build/tools/content.js.map +1 -0
  45. package/build/tools/errors.d.ts +3 -0
  46. package/build/tools/errors.js +55 -0
  47. package/build/tools/errors.js.map +1 -0
  48. package/build/tools/index-management.d.ts +30 -0
  49. package/build/tools/index-management.js +64 -0
  50. package/build/tools/index-management.js.map +1 -0
  51. package/build/tools/labels.d.ts +108 -0
  52. package/build/tools/labels.js +160 -0
  53. package/build/tools/labels.js.map +1 -0
  54. package/build/tools/permissions.d.ts +554 -0
  55. package/build/tools/permissions.js +194 -0
  56. package/build/tools/permissions.js.map +1 -0
  57. package/build/tools/spaces-admin.d.ts +225 -0
  58. package/build/tools/spaces-admin.js +288 -0
  59. package/build/tools/spaces-admin.js.map +1 -0
  60. package/build/tools/spaces-pages.d.ts +103 -0
  61. package/build/tools/spaces-pages.js +150 -0
  62. package/build/tools/spaces-pages.js.map +1 -0
  63. package/build/tools/system.d.ts +42 -0
  64. package/build/tools/system.js +101 -0
  65. package/build/tools/system.js.map +1 -0
  66. package/build/tools/users-groups.d.ts +216 -0
  67. package/build/tools/users-groups.js +274 -0
  68. package/build/tools/users-groups.js.map +1 -0
  69. package/build/tools/webhooks.d.ts +105 -0
  70. package/build/tools/webhooks.js +124 -0
  71. package/build/tools/webhooks.js.map +1 -0
  72. package/build/version.d.ts +7 -0
  73. package/build/version.js +17 -0
  74. package/build/version.js.map +1 -0
  75. package/docs/api-catalog.yaml +2388 -0
  76. package/package.json +59 -0
  77. package/skills/content.md +85 -0
  78. package/skills/instance-maintenance.md +59 -0
  79. package/skills/permissions.md +47 -0
  80. package/skills/spaces-admin.md +59 -0
  81. package/skills/spaces-pages.md +24 -0
  82. package/skills/system.md +34 -0
  83. package/skills/users-groups.md +55 -0
  84. package/skills/webhooks.md +25 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chuck
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # Castor for Confluence Data Center
2
+
3
+ Docs: https://castor.moosejudge.com/docs
4
+
5
+ A secure MCP server that bridges Atlassian Confluence Data Center (9.2 and 10.2, the two current
6
+ LTS lines) with AI agents like Claude.
7
+
8
+ > Castor is an independent, community-built tool. It is not affiliated with, endorsed by, or
9
+ > sponsored by Atlassian. Confluence® is a registered trademark of Atlassian Pty Ltd.
10
+
11
+ ## Overview
12
+
13
+ As Atlassian sunsets Data Center support, this server ensures organizations can still leverage AI
14
+ safely within their on-premise Confluence infrastructure. It follows open standards, the MCP
15
+ specification, and a "secure by default" model — see `alces-mcp` (the sibling Jira DC server this
16
+ project mirrors) for the shared design lineage.
17
+
18
+ ## Features
19
+
20
+ - **7 domain tools** covering spaces, pages, and CQL search, plus `get_api_references` for
21
+ querying the generated API catalog — `docs/api-catalog.md` tracks the full set of cataloged
22
+ Confluence DC operations and which are implemented.
23
+ - **Dual-token security**: `CONFLUENCE_USER_TOKEN` for standard operations,
24
+ `CONFLUENCE_ADMIN_TOKEN` for elevated ones (e.g. `admin_get_space_permissions`) — admin tools are
25
+ invisible to the agent without the admin token configured.
26
+ - **Skills as MCP Resources**: agent-facing operational guidance via `skill://spaces-pages`.
27
+
28
+ ## Install to use
29
+
30
+ Just want to talk to your Confluence DC instance through Claude Desktop, without cloning or
31
+ building anything? Install the pre-built bundle:
32
+
33
+ 1. Download the latest `castor-mcp-<version>.mcpb` from the
34
+ [GitLab Releases page](https://gitlab.com/moosejudge/castor-mcp/-/releases).
35
+ 2. In Claude Desktop: **Settings → Extensions → Advanced settings → Extension Developer →
36
+ "Install Extension…"**, then select the downloaded file.
37
+ 3. Enter your Confluence URL and PAT(s) when prompted — these are stored via your OS keychain,
38
+ never as plaintext.
39
+
40
+ Once connected, see [docs/user/](./docs/user/spaces-pages.md) for what you can do and how to ask
41
+ for it.
42
+
43
+ If you're integrating Castor into a coding agent instead of Claude Desktop, it's also published on
44
+ npm as [`castor-mcp`](https://www.npmjs.com/package/castor-mcp) — point your agent's MCP config at
45
+ `command: "npx"`, `args: ["-y", "castor-mcp"]` instead of cloning or building anything. See
46
+ [Setup to develop](#setup-to-develop) below only if you're contributing or need to run from an
47
+ unreleased commit.
48
+
49
+ ## Setup to develop
50
+
51
+ 1. Clone the repository.
52
+ 2. Install dependencies:
53
+ ```bash
54
+ npm install
55
+ ```
56
+ 3. Copy `.env.example` to `.env` and fill in `CONFLUENCE_URL` and `CONFLUENCE_USER_TOKEN`
57
+ (optionally `CONFLUENCE_ADMIN_TOKEN`).
58
+ 4. Build the project:
59
+ ```bash
60
+ npm run build
61
+ ```
62
+ 5. Run tests:
63
+ ```bash
64
+ npm test
65
+ ```
66
+
67
+ There is no running local Confluence instance yet — `docker-compose.yml` defines one (see
68
+ `docs/developer/testing-environment.md`), but it requires a Confluence developer license this
69
+ project does not currently have, and has never been started.
70
+
71
+ ## Documentation
72
+
73
+ - `docs/user/` — task-oriented guide to what the agent can do.
74
+ - `docs/developer/` — codebase notes for contributors.
75
+ - `docs/api-catalog.md` — generated reference of every cataloged Confluence DC operation and its
76
+ implementation status.
77
+ - `docs/specs/`, `docs/plans/` — design specs and implementation plans.
@@ -0,0 +1,27 @@
1
+ export interface ApiOperation {
2
+ api: string;
3
+ path: string;
4
+ method: string;
5
+ tag: string;
6
+ operation_id: string | null;
7
+ summary: string;
8
+ deprecated: boolean;
9
+ auth_tier: "user" | "admin";
10
+ destructiveness: string;
11
+ min_version: string;
12
+ max_version: string;
13
+ implementation_status: string;
14
+ implemented_by: string | null;
15
+ }
16
+ export interface ApiCatalog {
17
+ generated_from: string[];
18
+ generated_note: string;
19
+ operations: ApiOperation[];
20
+ }
21
+ export type ApiReferenceCategory = "user" | "admin";
22
+ export interface ApiReferenceArgs {
23
+ category?: ApiReferenceCategory;
24
+ tag?: string;
25
+ search?: string;
26
+ }
27
+ export declare function buildApiReferenceText(catalog: ApiCatalog, args: ApiReferenceArgs): string;
@@ -0,0 +1,76 @@
1
+ const ROW_DUMP_THRESHOLD = 80;
2
+ const MAX_ROWS = 150;
3
+ function opsForCategory(catalog, category) {
4
+ return catalog.operations.filter((o) => o.auth_tier === category);
5
+ }
6
+ function applyFilters(ops, args) {
7
+ let out = ops;
8
+ if (args.tag) {
9
+ const needle = args.tag.toLowerCase();
10
+ out = out.filter((o) => o.tag.toLowerCase().includes(needle));
11
+ }
12
+ if (args.search) {
13
+ const needle = args.search.toLowerCase();
14
+ out = out.filter((o) => o.path.toLowerCase().includes(needle) ||
15
+ o.summary.toLowerCase().includes(needle) ||
16
+ (o.operation_id ?? "").toLowerCase().includes(needle));
17
+ }
18
+ return out;
19
+ }
20
+ function tagBreakdown(ops) {
21
+ const counts = new Map();
22
+ for (const op of ops)
23
+ counts.set(op.tag, (counts.get(op.tag) ?? 0) + 1);
24
+ return [...counts.entries()]
25
+ .sort((a, b) => b[1] - a[1])
26
+ .map(([tag, count]) => `- \`${tag}\` (${count})`)
27
+ .join("\n");
28
+ }
29
+ function renderRows(ops) {
30
+ const truncated = ops.length > MAX_ROWS;
31
+ const rows = ops.slice(0, MAX_ROWS);
32
+ let md = `| Status | Method | Path | Summary | Kind |\n|---|---|---|---|---|\n`;
33
+ for (const op of rows) {
34
+ md += `| ${op.implementation_status} | ${op.method} | \`${op.path}\` | ${op.summary} | ${op.destructiveness} |\n`;
35
+ }
36
+ if (truncated) {
37
+ md += `\n_...${ops.length - MAX_ROWS} more rows omitted — narrow with \`tag\` or \`search\`._\n`;
38
+ }
39
+ return md;
40
+ }
41
+ function renderOverview(catalog) {
42
+ const counts = {
43
+ user: opsForCategory(catalog, "user").length,
44
+ admin: opsForCategory(catalog, "admin").length,
45
+ };
46
+ return [
47
+ `Confluence DC API catalog — ${catalog.operations.length} cataloged operations.`,
48
+ ``,
49
+ `Call again with a \`category\` to see entries:`,
50
+ `- \`user\` (${counts.user}) — user-tier`,
51
+ `- \`admin\` (${counts.admin}) — admin-tier`,
52
+ ``,
53
+ `Add \`tag\` or \`search\` to narrow within a category.`,
54
+ ``,
55
+ catalog.generated_note,
56
+ ].join("\n");
57
+ }
58
+ export function buildApiReferenceText(catalog, args) {
59
+ if (!args.category)
60
+ return renderOverview(catalog);
61
+ const base = opsForCategory(catalog, args.category);
62
+ const filtered = applyFilters(base, args);
63
+ if (filtered.length === 0) {
64
+ return `No operations found in category \`${args.category}\` matching the given filters.`;
65
+ }
66
+ if (filtered.length > ROW_DUMP_THRESHOLD && !args.tag && !args.search) {
67
+ return [
68
+ `Category \`${args.category}\` has ${filtered.length} operations — too many to list at once.`,
69
+ `Narrow with \`tag\` (or \`search\`). Tags in this category:`,
70
+ ``,
71
+ tagBreakdown(filtered),
72
+ ].join("\n");
73
+ }
74
+ return `${filtered.length} operation(s) in \`${args.category}\`${args.tag ? ` / tag "${args.tag}"` : ""}${args.search ? ` matching "${args.search}"` : ""}:\n\n${renderRows(filtered)}`;
75
+ }
76
+ //# sourceMappingURL=api-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-catalog.js","sourceRoot":"","sources":["../src/api-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { AxiosInstance } from "axios";
2
+ export interface ConfluenceConfig {
3
+ url: string;
4
+ token: string;
5
+ }
6
+ export declare class ConfluenceClient {
7
+ private axiosInstance;
8
+ constructor(config: ConfluenceConfig, axiosInstance?: AxiosInstance);
9
+ get(path: string, params?: Record<string, unknown>, responseType?: "json" | "arraybuffer"): Promise<import("axios").AxiosResponse<any, any, {}, Record<string, unknown>>>;
10
+ post(path: string, body?: unknown, headers?: Record<string, string | undefined>): Promise<import("axios").AxiosResponse<any, unknown, {}, any>>;
11
+ put(path: string, body?: unknown): Promise<import("axios").AxiosResponse<any, unknown, {}, any>>;
12
+ delete(path: string, params?: Record<string, unknown>): Promise<import("axios").AxiosResponse<any, any, {}, Record<string, unknown>>>;
13
+ /** GET /rest/api/space — list spaces, optionally filtered by type ("global"|"personal"). */
14
+ listSpaces(params?: {
15
+ type?: string;
16
+ limit?: number;
17
+ }): Promise<import("axios").AxiosResponse<any, any, {}, Record<string, unknown>>>;
18
+ /** GET /rest/api/space/{spaceKey} */
19
+ getSpace(spaceKey: string): Promise<import("axios").AxiosResponse<any, any, {}, Record<string, unknown>>>;
20
+ /**
21
+ * GET /rest/api/content/{id} — expands body.storage/version/space so callers get a page's
22
+ * content, version number, and owning space in one round trip.
23
+ */
24
+ getContent(id: string): Promise<import("axios").AxiosResponse<any, any, {}, Record<string, unknown>>>;
25
+ /** POST /rest/api/content */
26
+ createContent(body: unknown): Promise<import("axios").AxiosResponse<any, unknown, {}, any>>;
27
+ /** PUT /rest/api/content/{contentId} */
28
+ updateContent(contentId: string, body: unknown): Promise<import("axios").AxiosResponse<any, unknown, {}, any>>;
29
+ /** GET /rest/api/content/search — Confluence Query Language (CQL). */
30
+ searchContent(cql: string, limit?: number): Promise<import("axios").AxiosResponse<any, any, {}, Record<string, unknown>>>;
31
+ /** GET /rest/api/space/{spaceKey}/permissions — requires space-admin permission. */
32
+ getSpacePermissions(spaceKey: string): Promise<import("axios").AxiosResponse<any, any, {}, Record<string, unknown>>>;
33
+ }
@@ -0,0 +1,65 @@
1
+ import axios from "axios";
2
+ export class ConfluenceClient {
3
+ axiosInstance;
4
+ constructor(config, axiosInstance) {
5
+ if (axiosInstance) {
6
+ this.axiosInstance = axiosInstance;
7
+ return;
8
+ }
9
+ const baseUrl = config.url.endsWith("/") ? config.url.slice(0, -1) : config.url;
10
+ this.axiosInstance = axios.create({
11
+ baseURL: baseUrl,
12
+ headers: {
13
+ Authorization: `Bearer ${config.token}`,
14
+ "Content-Type": "application/json",
15
+ Accept: "application/json",
16
+ },
17
+ });
18
+ }
19
+ async get(path, params, responseType) {
20
+ return this.axiosInstance.get(path, { params, responseType });
21
+ }
22
+ async post(path, body, headers) {
23
+ if (headers)
24
+ return this.axiosInstance.post(path, body, { headers });
25
+ return this.axiosInstance.post(path, body);
26
+ }
27
+ async put(path, body) {
28
+ return this.axiosInstance.put(path, body);
29
+ }
30
+ async delete(path, params) {
31
+ return this.axiosInstance.delete(path, { params });
32
+ }
33
+ /** GET /rest/api/space — list spaces, optionally filtered by type ("global"|"personal"). */
34
+ async listSpaces(params) {
35
+ return this.get("/rest/api/space", params);
36
+ }
37
+ /** GET /rest/api/space/{spaceKey} */
38
+ async getSpace(spaceKey) {
39
+ return this.get(`/rest/api/space/${encodeURIComponent(spaceKey)}`);
40
+ }
41
+ /**
42
+ * GET /rest/api/content/{id} — expands body.storage/version/space so callers get a page's
43
+ * content, version number, and owning space in one round trip.
44
+ */
45
+ async getContent(id) {
46
+ return this.get(`/rest/api/content/${encodeURIComponent(id)}`, { expand: "body.storage,version,space" });
47
+ }
48
+ /** POST /rest/api/content */
49
+ async createContent(body) {
50
+ return this.post("/rest/api/content", body);
51
+ }
52
+ /** PUT /rest/api/content/{contentId} */
53
+ async updateContent(contentId, body) {
54
+ return this.put(`/rest/api/content/${encodeURIComponent(contentId)}`, body);
55
+ }
56
+ /** GET /rest/api/content/search — Confluence Query Language (CQL). */
57
+ async searchContent(cql, limit) {
58
+ return this.get("/rest/api/content/search", { cql, limit });
59
+ }
60
+ /** GET /rest/api/space/{spaceKey}/permissions — requires space-admin permission. */
61
+ async getSpacePermissions(spaceKey) {
62
+ return this.get(`/rest/api/space/${encodeURIComponent(spaceKey)}/permissions`);
63
+ }
64
+ }
65
+ //# sourceMappingURL=confluence-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confluence-client.js","sourceRoot":"","sources":["../src/confluence-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ReadResourceRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { readFile } from "fs/promises";
6
+ import { join, dirname } from "path";
7
+ import { fileURLToPath } from "url";
8
+ import dotenv from "dotenv";
9
+ import { load as loadYaml } from "js-yaml";
10
+ import { ConfluenceClient } from "./confluence-client.js";
11
+ import { TOOL_DEFINITIONS, listableToolEntries } from "./tool-definitions.js";
12
+ import { RESOURCE_DEFINITIONS, getResourceDefinition } from "./resource-definitions.js";
13
+ import { buildApiReferenceText } from "./api-catalog.js";
14
+ import { readPackageVersion } from "./version.js";
15
+ dotenv.config();
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = dirname(__filename);
18
+ class CastorMcpServer {
19
+ server;
20
+ userClient = null;
21
+ adminClient = null;
22
+ skillContentCache = new Map();
23
+ apiCatalogCache = null;
24
+ constructor() {
25
+ this.server = new Server({ name: "castor-mcp", version: readPackageVersion() }, {
26
+ capabilities: { tools: {}, resources: {} },
27
+ instructions: "Category-specific operational guidance is available as MCP Resources " +
28
+ "(skill://spaces-pages) — fetch it via resources/read before constructing complex " +
29
+ "CQL or working through a create/update page workflow.",
30
+ });
31
+ this.initializeClients();
32
+ this.setupHandlers();
33
+ this.server.onerror = (error) => console.error("[MCP Error]", error);
34
+ process.on("SIGINT", async () => {
35
+ await this.server.close();
36
+ process.exit(0);
37
+ });
38
+ }
39
+ initializeClients() {
40
+ const url = process.env.CONFLUENCE_URL;
41
+ const userToken = process.env.CONFLUENCE_USER_TOKEN;
42
+ const adminToken = process.env.CONFLUENCE_ADMIN_TOKEN;
43
+ if (!url) {
44
+ console.error("CONFLUENCE_URL is not set");
45
+ return;
46
+ }
47
+ if (userToken) {
48
+ this.userClient = new ConfluenceClient({ url, token: userToken });
49
+ }
50
+ if (adminToken) {
51
+ this.adminClient = new ConfluenceClient({ url, token: adminToken });
52
+ }
53
+ }
54
+ requireUserClient() {
55
+ if (!this.userClient) {
56
+ throw new McpError(ErrorCode.InvalidRequest, "No Confluence user client configured — set CONFLUENCE_URL and CONFLUENCE_USER_TOKEN.");
57
+ }
58
+ return this.userClient;
59
+ }
60
+ requireAdminClient() {
61
+ if (!this.adminClient) {
62
+ throw new McpError(ErrorCode.InvalidRequest, "No Confluence admin client configured — set CONFLUENCE_ADMIN_TOKEN to enable admin tools.");
63
+ }
64
+ return this.adminClient;
65
+ }
66
+ setupHandlers() {
67
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
68
+ tools: listableToolEntries(this.adminClient !== null).map(([name, def]) => ({
69
+ name,
70
+ description: def.description,
71
+ inputSchema: def.inputSchema,
72
+ })),
73
+ }));
74
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
75
+ const definition = TOOL_DEFINITIONS[request.params.name];
76
+ if (!definition) {
77
+ throw new McpError(ErrorCode.MethodNotFound, `Tool not found: ${request.params.name}`);
78
+ }
79
+ return definition.handler(this, request.params.arguments);
80
+ });
81
+ this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
82
+ resources: Object.values(RESOURCE_DEFINITIONS).map(({ uri, name, description, mimeType }) => ({
83
+ uri,
84
+ name,
85
+ description,
86
+ mimeType,
87
+ })),
88
+ }));
89
+ this.server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({ resourceTemplates: [] }));
90
+ this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
91
+ const def = getResourceDefinition(request.params.uri);
92
+ let text;
93
+ try {
94
+ text = await this.loadSkillContent(def.filePath);
95
+ }
96
+ catch {
97
+ throw new McpError(ErrorCode.InternalError, `Error reading skill resource ${def.uri}`);
98
+ }
99
+ return { contents: [{ uri: def.uri, mimeType: def.mimeType, text }] };
100
+ });
101
+ }
102
+ async loadSkillContent(filePath) {
103
+ const cached = this.skillContentCache.get(filePath);
104
+ if (cached !== undefined)
105
+ return cached;
106
+ const fullPath = join(__dirname, "..", "skills", filePath);
107
+ const text = await readFile(fullPath, "utf-8");
108
+ this.skillContentCache.set(filePath, text);
109
+ return text;
110
+ }
111
+ async loadApiCatalog() {
112
+ if (this.apiCatalogCache)
113
+ return this.apiCatalogCache;
114
+ const catalogPath = join(__dirname, "..", "docs", "api-catalog.yaml");
115
+ const raw = await readFile(catalogPath, "utf-8");
116
+ this.apiCatalogCache = loadYaml(raw);
117
+ return this.apiCatalogCache;
118
+ }
119
+ async handleGetApiReferences(args) {
120
+ try {
121
+ const catalog = await this.loadApiCatalog();
122
+ const text = buildApiReferenceText(catalog, (args ?? {}));
123
+ return { content: [{ type: "text", text }] };
124
+ }
125
+ catch (error) {
126
+ throw new McpError(ErrorCode.InternalError, `Error reading API catalog: ${error instanceof Error ? error.message : String(error)}`);
127
+ }
128
+ }
129
+ async run() {
130
+ const transport = new StdioServerTransport();
131
+ await this.server.connect(transport);
132
+ console.error("Castor MCP server running on stdio");
133
+ }
134
+ }
135
+ const server = new CastorMcpServer();
136
+ server.run().catch(console.error);
137
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface ResourceDefinition {
2
+ uri: string;
3
+ name: string;
4
+ description: string;
5
+ mimeType: string;
6
+ /** Relative to the skills/ directory at the repo root. */
7
+ filePath: string;
8
+ }
9
+ export declare const RESOURCE_DEFINITIONS: Record<string, ResourceDefinition>;
10
+ export declare function getResourceDefinition(uri: string): ResourceDefinition;
@@ -0,0 +1,75 @@
1
+ import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
2
+ export const RESOURCE_DEFINITIONS = {
3
+ "skill://spaces-pages": {
4
+ uri: "skill://spaces-pages",
5
+ name: "Confluence Spaces & Pages",
6
+ description: "CQL construction and page-versioning guidance for the spaces/pages tools.",
7
+ mimeType: "text/markdown",
8
+ filePath: "spaces-pages.md",
9
+ },
10
+ "skill://content": {
11
+ uri: "skill://content",
12
+ name: "Confluence Content",
13
+ description: "Content properties, structure, labels, bulk operations, and attachments — real gotchas " +
14
+ "found live-verifying content.ts, content-structure.ts, labels.ts, bulk-pages.ts, and " +
15
+ "attachments.ts.",
16
+ mimeType: "text/markdown",
17
+ filePath: "content.md",
18
+ },
19
+ "skill://spaces-admin": {
20
+ uri: "skill://spaces-admin",
21
+ name: "Confluence Space Administration",
22
+ description: "Space lifecycle (create/update/archive/delete/trash) and color scheme management — real " +
23
+ "gotchas found live-verifying spaces-admin.ts and color-schemes.ts.",
24
+ mimeType: "text/markdown",
25
+ filePath: "spaces-admin.md",
26
+ },
27
+ "skill://permissions": {
28
+ uri: "skill://permissions",
29
+ name: "Confluence Permissions",
30
+ description: "Global and space-scoped permission read/grant/revoke/set — real gotchas found " +
31
+ "live-verifying permissions.ts.",
32
+ mimeType: "text/markdown",
33
+ filePath: "permissions.md",
34
+ },
35
+ "skill://users-groups": {
36
+ uri: "skill://users-groups",
37
+ name: "Confluence Users & Groups",
38
+ description: "User/group lookup, membership, watching, and admin account management — real gotchas " +
39
+ "found live-verifying users-groups.ts and admin-users-groups.ts.",
40
+ mimeType: "text/markdown",
41
+ filePath: "users-groups.md",
42
+ },
43
+ "skill://webhooks": {
44
+ uri: "skill://webhooks",
45
+ name: "Confluence Webhooks",
46
+ description: "Webhook lifecycle and testing — real gotchas found live-verifying webhooks.ts.",
47
+ mimeType: "text/markdown",
48
+ filePath: "webhooks.md",
49
+ },
50
+ "skill://instance-maintenance": {
51
+ uri: "skill://instance-maintenance",
52
+ name: "Confluence Backup, Restore & Search Index",
53
+ description: "Backup/restore jobs and search index management, including which operations are " +
54
+ "genuinely irreversible — real gotchas found live-verifying backup-restore.ts and " +
55
+ "index-management.ts.",
56
+ mimeType: "text/markdown",
57
+ filePath: "instance-maintenance.md",
58
+ },
59
+ "skill://system": {
60
+ uri: "skill://system",
61
+ name: "Confluence System Info & Search",
62
+ description: "Audit records, cluster status, instance metrics, long-running tasks, cross-entity search, " +
63
+ "and server information — real gotchas found live-verifying system.ts.",
64
+ mimeType: "text/markdown",
65
+ filePath: "system.md",
66
+ },
67
+ };
68
+ export function getResourceDefinition(uri) {
69
+ const def = RESOURCE_DEFINITIONS[uri];
70
+ if (!def) {
71
+ throw new McpError(ErrorCode.InvalidParams, `Unknown resource: ${uri}`);
72
+ }
73
+ return def;
74
+ }
75
+ //# sourceMappingURL=resource-definitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-definitions.js","sourceRoot":"","sources":["../src/resource-definitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAWzE,MAAM,CAAC,MAAM,oBAAoB,GAAuC;IACtE,sBAAsB,EAAE;QACtB,GAAG,EAAE,sBAAsB;QAC3B,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,2EAA2E;QACxF,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,iBAAiB;KAC5B;IACD,iBAAiB,EAAE;QACjB,GAAG,EAAE,iBAAiB;QACtB,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,yFAAyF;YACzF,uFAAuF;YACvF,iBAAiB;QACnB,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,YAAY;KACvB;IACD,sBAAsB,EAAE;QACtB,GAAG,EAAE,sBAAsB;QAC3B,IAAI,EAAE,iCAAiC;QACvC,WAAW,EACT,0FAA0F;YAC1F,oEAAoE;QACtE,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,iBAAiB;KAC5B;IACD,qBAAqB,EAAE;QACrB,GAAG,EAAE,qBAAqB;QAC1B,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EACT,gFAAgF;YAChF,gCAAgC;QAClC,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,gBAAgB;KAC3B;IACD,sBAAsB,EAAE;QACtB,GAAG,EAAE,sBAAsB;QAC3B,IAAI,EAAE,2BAA2B;QACjC,WAAW,EACT,uFAAuF;YACvF,iEAAiE;QACnE,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,iBAAiB;KAC5B;IACD,kBAAkB,EAAE;QAClB,GAAG,EAAE,kBAAkB;QACvB,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,gFAAgF;QAC7F,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,aAAa;KACxB;IACD,8BAA8B,EAAE;QAC9B,GAAG,EAAE,8BAA8B;QACnC,IAAI,EAAE,2CAA2C;QACjD,WAAW,EACT,kFAAkF;YAClF,mFAAmF;YACnF,sBAAsB;QACxB,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,yBAAyB;KACpC;IACD,gBAAgB,EAAE;QAChB,GAAG,EAAE,gBAAgB;QACrB,IAAI,EAAE,iCAAiC;QACvC,WAAW,EACT,4FAA4F;YAC5F,uEAAuE;QACzE,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,WAAW;KACtB;CACF,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,GAAG,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { ConfluenceClient } from "./confluence-client.js";
2
+ import { type ToolResult } from "./tools/spaces-pages.js";
3
+ export interface ToolDefinitionServer {
4
+ requireUserClient(): ConfluenceClient;
5
+ requireAdminClient(): ConfluenceClient;
6
+ handleGetApiReferences(args: Record<string, unknown> | undefined): Promise<ToolResult>;
7
+ }
8
+ export interface ToolDefinition {
9
+ description: string;
10
+ inputSchema: Record<string, unknown>;
11
+ requiresAdmin?: boolean;
12
+ handler: (server: ToolDefinitionServer, args: unknown) => Promise<ToolResult>;
13
+ }
14
+ export declare const TOOL_DEFINITIONS: Record<string, ToolDefinition>;
15
+ /**
16
+ * Pure filter used by the ListTools handler — admin-flagged tools are dropped entirely from the
17
+ * advertised tool list when no admin client is configured, not just rejected at call time.
18
+ */
19
+ export declare function listableToolEntries(adminAvailable: boolean): Array<[string, ToolDefinition]>;