@sondt2709/wikijs-mcp 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["pkg.version"],"sources":["../src/config.ts","../src/logger.ts","../package.json","../src/client/graphql.ts","../src/client/wikijs.ts","../src/tools/result.ts","../src/tools/discovery.ts","../src/tools/pages.ts","../src/tools/history.ts","../src/tools/assets.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["import { parseArgs } from 'node:util';\nimport { z } from 'zod';\n\nconst ConfigSchema = z.object({\n wikijsUrl: z.url({ message: 'must be a valid URL like https://wiki.example.com' }),\n wikijsToken: z.string().min(1, 'must not be empty'),\n transport: z.enum(['stdio', 'http']).default('stdio'),\n port: z.coerce.number().int().min(1).max(65535).default(3000),\n logLevel: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport function loadConfig(argv: string[] = process.argv.slice(2)): Config {\n const { values } = parseArgs({\n args: argv,\n options: {\n url: { type: 'string' },\n token: { type: 'string' },\n transport: { type: 'string' },\n port: { type: 'string' },\n 'log-level': { type: 'string' },\n },\n });\n\n const parsed = ConfigSchema.safeParse({\n wikijsUrl: values.url ?? process.env.WIKIJS_URL,\n wikijsToken: values.token ?? process.env.WIKIJS_TOKEN,\n transport: values.transport ?? process.env.TRANSPORT,\n port: values.port ?? process.env.PORT,\n logLevel: values['log-level'] ?? process.env.LOG_LEVEL,\n });\n\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(\n `Invalid configuration — ${issues}. ` +\n 'Set WIKIJS_URL and WIKIJS_TOKEN env vars (or --url/--token flags). See .env.example.',\n );\n }\n return parsed.data;\n}\n","import pino, { destination } from 'pino';\n\nexport function createLogger(level: string) {\n return pino({ level, base: undefined }, destination(2));\n}\n\nexport type Logger = ReturnType<typeof createLogger>;\n","","export type ErrorKind = 'transport' | 'graphql' | 'application';\n\nexport class WikiJsError extends Error {\n readonly kind: ErrorKind;\n readonly slug?: string;\n readonly errorCode?: number;\n\n constructor(message: string, kind: ErrorKind, slug?: string, errorCode?: number) {\n super(message);\n this.name = 'WikiJsError';\n this.kind = kind;\n this.slug = slug;\n this.errorCode = errorCode;\n }\n}\n\nexport interface ResponseStatus {\n succeeded: boolean;\n errorCode: number;\n slug: string;\n message?: string | null;\n}\n\nexport function assertSucceeded(rr: ResponseStatus, action: string): void {\n if (!rr.succeeded) {\n throw new WikiJsError(\n `Wiki.js error ${rr.slug} while ${action}: ${rr.message ?? 'no message provided'}`,\n 'application',\n rr.slug,\n rr.errorCode,\n );\n }\n}\n\nconst AUTH_HINT =\n ' (check that WIKIJS_TOKEN is a valid, unexpired API key and that its group has the required page permissions)';\n\nexport interface GraphQLClientOptions {\n baseUrl: string;\n token: string;\n timeoutMs?: number;\n}\n\nexport class GraphQLClient {\n private readonly endpoint: string;\n private readonly token: string;\n private readonly timeoutMs: number;\n\n constructor(opts: GraphQLClientOptions) {\n this.endpoint = new URL('/graphql', opts.baseUrl).toString();\n this.token = opts.token;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n\n async request<T>(query: string, variables?: Record<string, unknown>): Promise<T> {\n let res: Response;\n try {\n res = await fetch(this.endpoint, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.token}`,\n },\n body: JSON.stringify({ query, variables }),\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n throw new WikiJsError(\n `Cannot reach Wiki.js at ${this.endpoint}: ${(err as Error).message}`,\n 'transport',\n );\n }\n\n if (res.status === 401 || res.status === 403) {\n throw new WikiJsError(\n `Wiki.js rejected the request with HTTP ${res.status}${AUTH_HINT}`,\n 'transport',\n );\n }\n if (!res.ok) {\n throw new WikiJsError(`Wiki.js returned HTTP ${res.status} for GraphQL request`, 'transport');\n }\n\n let body: { data?: T; errors?: { message: string }[] };\n try {\n body = (await res.json()) as { data?: T; errors?: { message: string }[] };\n } catch {\n throw new WikiJsError(\n `Wiki.js returned a non-JSON response (HTTP ${res.status})`,\n 'transport',\n );\n }\n if (body.errors?.length) {\n const message = body.errors.map((e) => e.message).join('; ');\n const isAuth = /forbidden|unauthorized|not authorized/i.test(message);\n throw new WikiJsError(`GraphQL error: ${message}${isAuth ? AUTH_HINT : ''}`, 'graphql');\n }\n if (body.data == null) {\n throw new WikiJsError('Wiki.js returned an empty GraphQL response', 'graphql');\n }\n return body.data;\n }\n}\n","import { z } from 'zod';\nimport {\n assertSucceeded,\n WikiJsError,\n type GraphQLClient,\n type ResponseStatus,\n} from './graphql.ts';\n\n// Wiki.js's GraphQL layer reports a missing page as a top-level GraphQL error\n// (\"PageNotFound 6003: This page does not exist.\") rather than only returning\n// `data.pages.single(ByPath) === null`. GraphQLClient.request() throws on any\n// top-level error, so we must catch that specific case here and translate it\n// back into the `null` result the brief's read methods contract expects.\nfunction isPageNotFoundError(err: unknown): boolean {\n return (\n err instanceof WikiJsError && err.kind === 'graphql' && /does not exist/i.test(err.message)\n );\n}\n\n// --- zod schemas for Wiki.js responses (trimmed to fields we expose) ---\n\nconst SearchResultSchema = z.object({\n id: z.string(),\n title: z.string(),\n description: z.string(),\n path: z.string(),\n locale: z.string(),\n});\nexport type SearchResult = z.infer<typeof SearchResultSchema>;\n\nconst SearchResponseSchema = z.object({\n results: z.array(SearchResultSchema),\n suggestions: z\n .array(z.string().nullable())\n .transform((a) => a.filter((s): s is string => s != null)),\n totalHits: z.number(),\n});\n\nconst PageListItemSchema = z.object({\n id: z.number(),\n path: z.string(),\n locale: z.string(),\n title: z.string().nullish(),\n description: z.string().nullish(),\n contentType: z.string(),\n isPublished: z.boolean(),\n isPrivate: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n tags: z\n .array(z.string().nullable())\n .nullish()\n .transform((a) => (a ?? []).filter((t): t is string => t != null)),\n});\nexport type PageListItem = z.infer<typeof PageListItemSchema>;\n\nconst PageDetailSchema = z.object({\n id: z.number(),\n path: z.string(),\n locale: z.string(),\n title: z.string(),\n description: z.string(),\n content: z.string(),\n contentType: z.string(),\n editor: z.string(),\n isPublished: z.boolean(),\n isPrivate: z.boolean(),\n tags: z\n .array(z.object({ tag: z.string() }).nullable())\n .transform((a) => a.filter((t): t is { tag: string } => t != null).map((t) => t.tag)),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\nexport type PageDetail = z.infer<typeof PageDetailSchema>;\n\nconst TreeItemSchema = z.object({\n id: z.number(),\n path: z.string(),\n depth: z.number(),\n title: z.string(),\n isFolder: z.boolean(),\n pageId: z.number().nullish(),\n parent: z.number().nullish(),\n locale: z.string(),\n});\nexport type TreeItem = z.infer<typeof TreeItemSchema>;\n\nconst TagSchema = z.object({\n id: z.number(),\n tag: z.string(),\n title: z.string().nullish(),\n});\nexport type Tag = z.infer<typeof TagSchema>;\n\nconst PAGE_DETAIL_FIELDS = `\n id path locale title description content contentType editor\n isPublished isPrivate tags { tag } createdAt updatedAt\n`;\n\nconst PageRefSchema = z.object({\n id: z.number(),\n path: z.string(),\n locale: z.string(),\n title: z.string(),\n});\nexport type PageRef = z.infer<typeof PageRefSchema>;\n\n// Wiki.js server bug: the `create` and `update` mutations throw\n// \"Cannot return null for non-nullable field Page.locale\" (HTTP 200 with a\n// top-level GraphQL error) if `locale` is included in the returned `page`\n// selection — the in-memory object handed back to the resolver never gets a\n// `locale` populated, only a DB refetch (e.g. pages.single) has it. `id`,\n// `path`, and `title` come back fine. So we omit `locale` from these two\n// mutations' `page` selection and fill it in ourselves (see createPage /\n// updatePage) instead of using the full PageRefSchema here.\nconst MutationPageSchema = z.object({\n id: z.number(),\n path: z.string(),\n title: z.string(),\n});\n\nconst MutationResponseSchema = z.object({\n responseResult: z.object({\n succeeded: z.boolean(),\n errorCode: z.number(),\n slug: z.string(),\n message: z.string().nullish(),\n }),\n page: MutationPageSchema.nullish(),\n});\n\nconst HistoryEntrySchema = z.object({\n versionId: z.number(),\n versionDate: z.string(),\n authorId: z.number(),\n authorName: z.string(),\n actionType: z.string(),\n valueBefore: z.string().nullish(),\n valueAfter: z.string().nullish(),\n});\nexport type HistoryEntry = z.infer<typeof HistoryEntrySchema>;\n\nconst PageVersionSchema = z.object({\n versionId: z.number(),\n versionDate: z.string(),\n action: z.string(),\n authorName: z.string(),\n pageId: z.number(),\n path: z.string(),\n locale: z.string(),\n title: z.string(),\n description: z.string(),\n content: z.string(),\n contentType: z.string(),\n editor: z.string(),\n isPublished: z.boolean(),\n tags: z.array(z.string().nullable()).transform((a) => a.filter((t): t is string => t != null)),\n createdAt: z.string(),\n});\nexport type PageVersion = z.infer<typeof PageVersionSchema>;\n\nconst AssetFolderSchema = z.object({\n id: z.number(),\n slug: z.string(),\n name: z.string().nullish(),\n});\nexport type AssetFolder = z.infer<typeof AssetFolderSchema>;\n\nconst AssetItemSchema = z.object({\n id: z.number(),\n filename: z.string(),\n ext: z.string(),\n kind: z.string(),\n mime: z.string(),\n fileSize: z.number(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\nexport type AssetItem = z.infer<typeof AssetItemSchema>;\n\nexport interface CreatePageInput {\n path: string;\n title: string;\n content: string;\n description?: string;\n editor?: string;\n locale?: string;\n isPublished?: boolean;\n isPrivate?: boolean;\n tags?: string[];\n}\n\nexport interface UpdatePageInput {\n id: number;\n content?: string;\n title?: string;\n description?: string;\n isPublished?: boolean;\n isPrivate?: boolean;\n tags?: string[];\n path?: string;\n locale?: string;\n}\n\nexport class WikiJsClient {\n private readonly gql: GraphQLClient;\n\n constructor(gql: GraphQLClient) {\n this.gql = gql;\n }\n\n async searchPages(args: { query: string; path?: string; locale?: string }) {\n const data = await this.gql.request<{ pages: { search: unknown } }>(\n `query ($query: String!, $path: String, $locale: String) {\n pages { search(query: $query, path: $path, locale: $locale) {\n results { id title description path locale }\n suggestions\n totalHits\n } }\n }`,\n args,\n );\n return SearchResponseSchema.parse(data.pages.search);\n }\n\n async listPages(args: {\n limit?: number;\n orderBy?: string;\n orderByDirection?: string;\n tags?: string[];\n locale?: string;\n }) {\n const data = await this.gql.request<{ pages: { list: unknown } }>(\n `query ($limit: Int, $orderBy: PageOrderBy, $orderByDirection: PageOrderByDirection, $tags: [String!], $locale: String) {\n pages { list(limit: $limit, orderBy: $orderBy, orderByDirection: $orderByDirection, tags: $tags, locale: $locale) {\n id path locale title description contentType isPublished isPrivate createdAt updatedAt tags\n } }\n }`,\n args,\n );\n return z.array(PageListItemSchema).parse(data.pages.list);\n }\n\n async getPageById(id: number) {\n try {\n const data = await this.gql.request<{ pages: { single: unknown } }>(\n `query ($id: Int!) { pages { single(id: $id) { ${PAGE_DETAIL_FIELDS} } } }`,\n { id },\n );\n return data.pages.single == null ? null : PageDetailSchema.parse(data.pages.single);\n } catch (err) {\n if (isPageNotFoundError(err)) return null;\n throw err;\n }\n }\n\n async getPageByPath(path: string, locale: string) {\n try {\n const data = await this.gql.request<{ pages: { singleByPath: unknown } }>(\n `query ($path: String!, $locale: String!) { pages { singleByPath(path: $path, locale: $locale) { ${PAGE_DETAIL_FIELDS} } } }`,\n { path, locale },\n );\n return data.pages.singleByPath == null\n ? null\n : PageDetailSchema.parse(data.pages.singleByPath);\n } catch (err) {\n if (isPageNotFoundError(err)) return null;\n throw err;\n }\n }\n\n async getTree(args: {\n parent?: number;\n path?: string;\n mode: 'ALL' | 'PAGES' | 'FOLDERS';\n locale: string;\n includeAncestors?: boolean;\n }) {\n // Wiki.js's pages.tree resolver throws \"builder.andWhereNotNull is not a\n // function\" when mode is PAGES: server/graph/resolvers/page.js:273 calls a\n // knex builder method that doesn't exist, unconditionally, for that mode.\n // ALL and FOLDERS are unaffected. We work around it by always requesting\n // ALL from the server and, when the caller asked for PAGES, filtering out\n // folders client-side (ALL includes an isFolder flag on every item).\n const requestMode = args.mode === 'PAGES' ? 'ALL' : args.mode;\n const data = await this.gql.request<{ pages: { tree: unknown } }>(\n `query ($parent: Int, $path: String, $mode: PageTreeMode!, $locale: String!, $includeAncestors: Boolean) {\n pages { tree(parent: $parent, path: $path, mode: $mode, locale: $locale, includeAncestors: $includeAncestors) {\n id path depth title isFolder pageId parent locale\n } }\n }`,\n { ...args, mode: requestMode },\n );\n const items = z\n .array(TreeItemSchema.nullable())\n .parse(data.pages.tree ?? [])\n .filter((t): t is TreeItem => t != null);\n return args.mode === 'PAGES' ? items.filter((t) => !t.isFolder) : items;\n }\n\n async listTags() {\n const data = await this.gql.request<{ pages: { tags: unknown } }>(\n `query { pages { tags { id tag title } } }`,\n );\n return z\n .array(TagSchema.nullable())\n .parse(data.pages.tags)\n .filter((t): t is Tag => t != null);\n }\n\n async searchTags(query: string) {\n const data = await this.gql.request<{ pages: { searchTags: unknown } }>(\n `query ($query: String!) { pages { searchTags(query: $query) } }`,\n { query },\n );\n return z\n .array(z.string().nullable())\n .parse(data.pages.searchTags)\n .filter((t): t is string => t != null);\n }\n\n async createPage(input: CreatePageInput): Promise<PageRef> {\n const data = await this.gql.request<{ pages: { create: unknown } }>(\n `mutation ($content: String!, $description: String!, $editor: String!, $isPublished: Boolean!,\n $isPrivate: Boolean!, $locale: String!, $path: String!, $tags: [String]!, $title: String!) {\n pages { create(content: $content, description: $description, editor: $editor, isPublished: $isPublished,\n isPrivate: $isPrivate, locale: $locale, path: $path, tags: $tags, title: $title) {\n responseResult { succeeded errorCode slug message }\n page { id path title }\n } }\n }`,\n {\n content: input.content,\n description: input.description ?? '',\n editor: input.editor ?? 'markdown',\n isPublished: input.isPublished ?? true,\n isPrivate: input.isPrivate ?? false,\n locale: input.locale ?? 'en',\n path: input.path,\n tags: input.tags ?? [],\n title: input.title,\n },\n );\n const res = MutationResponseSchema.parse(data.pages.create);\n assertSucceeded(res.responseResult, `creating page at ${input.path}`);\n if (!res.page)\n throw new WikiJsError('Wiki.js reported success but returned no page', 'application');\n // See MutationPageSchema comment: the mutation can't safely report its own\n // `locale`, but we know it because we're the ones who just requested it.\n return PageRefSchema.parse({ ...res.page, locale: input.locale ?? 'en' });\n }\n\n async updatePage(input: UpdatePageInput): Promise<PageRef> {\n const { id, ...fields } = input;\n // Constraint: Wiki.js's pages.update mutation requires a concrete `tags`\n // array and non-empty `content` — passing undefined/null (or empty\n // content) throws server-side. It also *defaults* `isPublished` and\n // `isPrivate` to `false` server-side when their variables are omitted\n // (rather than leaving the existing value alone), which silently\n // unpublishes/exposes a page on an unrelated metadata-only update (e.g. a\n // title change). When the caller omits content/tags/isPublished/isPrivate,\n // fetch the page's current state once and resend the existing value\n // unchanged so the update doesn't clear/crash on tags/content or flip\n // isPublished/isPrivate. Caller-supplied values always win.\n const needsCurrent =\n fields.tags == null ||\n fields.content == null ||\n fields.isPublished == null ||\n fields.isPrivate == null;\n const current = needsCurrent ? await this.getPageById(id) : null;\n const tags = fields.tags ?? current?.tags ?? [];\n const content = fields.content ?? current?.content;\n const isPublished = fields.isPublished ?? current?.isPublished;\n const isPrivate = fields.isPrivate ?? current?.isPrivate;\n const data = await this.gql.request<{ pages: { update: unknown } }>(\n `mutation ($id: Int!, $content: String, $description: String, $isPrivate: Boolean, $isPublished: Boolean,\n $locale: String, $path: String, $tags: [String]!, $title: String) {\n pages { update(id: $id, content: $content, description: $description, isPrivate: $isPrivate,\n isPublished: $isPublished, locale: $locale, path: $path, tags: $tags, title: $title) {\n responseResult { succeeded errorCode slug message }\n page { id path title }\n } }\n }`,\n { id, ...fields, tags, content, isPublished, isPrivate },\n );\n const res = MutationResponseSchema.parse(data.pages.update);\n assertSucceeded(res.responseResult, `updating page ${id}`);\n if (!res.page)\n throw new WikiJsError('Wiki.js reported success but returned no page', 'application');\n // See MutationPageSchema comment: unlike createPage, we can't infer the\n // resulting locale from the input (the caller may not have changed it),\n // so re-fetch the page to report its actual post-update locale.\n const updated = await this.getPageById(id);\n if (!updated) {\n throw new WikiJsError(\n `Page ${id} vanished immediately after a successful update`,\n 'application',\n );\n }\n return PageRefSchema.parse({\n id: updated.id,\n path: updated.path,\n locale: updated.locale,\n title: updated.title,\n });\n }\n\n async movePage(id: number, destinationPath: string, destinationLocale: string): Promise<void> {\n const data = await this.gql.request<{ pages: { move: unknown } }>(\n `mutation ($id: Int!, $destinationPath: String!, $destinationLocale: String!) {\n pages { move(id: $id, destinationPath: $destinationPath, destinationLocale: $destinationLocale) {\n responseResult { succeeded errorCode slug message }\n } }\n }`,\n { id, destinationPath, destinationLocale },\n );\n const res: { responseResult: ResponseStatus } = z\n .object({ responseResult: MutationResponseSchema.shape.responseResult })\n .parse(data.pages.move);\n assertSucceeded(\n res.responseResult,\n `moving page ${id} to ${destinationLocale}/${destinationPath}`,\n );\n }\n\n async deletePage(id: number): Promise<void> {\n const data = await this.gql.request<{ pages: { delete: unknown } }>(\n `mutation ($id: Int!) {\n pages { delete(id: $id) { responseResult { succeeded errorCode slug message } } }\n }`,\n { id },\n );\n const res: { responseResult: ResponseStatus } = z\n .object({ responseResult: MutationResponseSchema.shape.responseResult })\n .parse(data.pages.delete);\n assertSucceeded(res.responseResult, `deleting page ${id}`);\n }\n\n async getHistory(id: number, offsetPage?: number, offsetSize?: number) {\n const data = await this.gql.request<{ pages: { history: unknown } }>(\n `query ($id: Int!, $offsetPage: Int, $offsetSize: Int) {\n pages { history(id: $id, offsetPage: $offsetPage, offsetSize: $offsetSize) {\n trail { versionId versionDate authorId authorName actionType valueBefore valueAfter }\n total\n } }\n }`,\n { id, offsetPage, offsetSize },\n );\n return z\n .object({\n trail: z\n .array(HistoryEntrySchema.nullable())\n .nullish()\n .transform((a) => (a ?? []).filter((e): e is HistoryEntry => e != null)),\n total: z.number(),\n })\n .parse(data.pages.history);\n }\n\n async getVersion(pageId: number, versionId: number): Promise<PageVersion> {\n const data = await this.gql.request<{ pages: { version: unknown } }>(\n `query ($pageId: Int!, $versionId: Int!) {\n pages { version(pageId: $pageId, versionId: $versionId) {\n versionId versionDate action authorName pageId path locale title description\n content contentType editor isPublished tags createdAt\n } }\n }`,\n { pageId, versionId },\n );\n if (data.pages.version == null) {\n throw new WikiJsError(`Version ${versionId} of page ${pageId} not found`, 'application');\n }\n return PageVersionSchema.parse(data.pages.version);\n }\n\n async restoreVersion(pageId: number, versionId: number): Promise<void> {\n const data = await this.gql.request<{ pages: { restore: unknown } }>(\n `mutation ($pageId: Int!, $versionId: Int!) {\n pages { restore(pageId: $pageId, versionId: $versionId) {\n responseResult { succeeded errorCode slug message }\n } }\n }`,\n { pageId, versionId },\n );\n const res: { responseResult: ResponseStatus } = z\n .object({ responseResult: MutationResponseSchema.shape.responseResult })\n .parse(data.pages.restore);\n assertSucceeded(res.responseResult, `restoring page ${pageId} to version ${versionId}`);\n }\n\n async listAssetFolders(parentFolderId: number) {\n const data = await this.gql.request<{ assets: { folders: unknown } }>(\n `query ($parentFolderId: Int!) { assets { folders(parentFolderId: $parentFolderId) { id slug name } } }`,\n { parentFolderId },\n );\n return z\n .array(AssetFolderSchema.nullable())\n .parse(data.assets.folders ?? [])\n .filter((f): f is AssetFolder => f != null);\n }\n\n async listAssets(folderId: number, kind: 'IMAGE' | 'BINARY' | 'ALL') {\n const data = await this.gql.request<{ assets: { list: unknown } }>(\n `query ($folderId: Int!, $kind: AssetKind!) {\n assets { list(folderId: $folderId, kind: $kind) {\n id filename ext kind mime fileSize createdAt updatedAt\n } }\n }`,\n { folderId, kind },\n );\n return z\n .array(AssetItemSchema.nullable())\n .parse(data.assets.list ?? [])\n .filter((a): a is AssetItem => a != null);\n }\n}\n","import { WikiJsError } from '../client/graphql.ts';\nimport type { Logger } from '../logger.ts';\n\ninterface TextContent {\n type: 'text';\n text: string;\n}\n\n/**\n * Wraps a tool handler to log its name and duration (ms) at debug level on\n * every call. Never logs arguments or tokens — timing/name only.\n */\nexport function instrument<A extends unknown[], R>(\n logger: Logger,\n name: string,\n handler: (...args: A) => Promise<R>,\n): (...args: A) => Promise<R> {\n return async (...args: A): Promise<R> => {\n const start = performance.now();\n try {\n return await handler(...args);\n } finally {\n const durationMs = performance.now() - start;\n logger.debug({ tool: name, durationMs }, 'tool call');\n }\n };\n}\n\nexport function ok<T extends Record<string, unknown>>(\n structured: T,\n summary?: string,\n): { content: TextContent[]; structuredContent: T } {\n const json = JSON.stringify(structured);\n return {\n content: [{ type: 'text', text: summary ? `${summary}\\n\\n${json}` : json }],\n structuredContent: structured,\n };\n}\n\nexport function fail(err: unknown): { content: TextContent[]; isError: true } {\n const text = err instanceof WikiJsError || err instanceof Error ? err.message : String(err);\n return { content: [{ type: 'text', text }], isError: true };\n}\n\n/**\n * Slices text content by 0-based, inclusive line range. Negative bounds\n * count from the end (Python-style: -1 = last line). Bounds are clamped to\n * the available lines, and an empty result is returned if start > end.\n */\nexport function sliceLines(\n content: string,\n startLine: number,\n endLine: number,\n): { content: string; totalLines: number; startLine: number; endLine: number } {\n const lines = content === '' ? [] : content.split('\\n');\n const totalLines = lines.length;\n\n if (totalLines === 0) {\n return { content: '', totalLines: 0, startLine: 0, endLine: 0 };\n }\n\n const resolveIndex = (n: number): number => (n < 0 ? totalLines + n : n);\n const clamp = (n: number): number => Math.min(Math.max(n, 0), totalLines - 1);\n\n const resolvedStart = clamp(resolveIndex(startLine));\n const resolvedEnd = clamp(resolveIndex(endLine));\n\n const slicedContent =\n resolvedStart > resolvedEnd ? '' : lines.slice(resolvedStart, resolvedEnd + 1).join('\\n');\n\n return { content: slicedContent, totalLines, startLine: resolvedStart, endLine: resolvedEnd };\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { WikiJsClient } from '../client/wikijs.ts';\nimport type { Logger } from '../logger.ts';\nimport { ok, fail, instrument, sliceLines } from './result.ts';\n\nconst pageSummaryShape = {\n id: z.number(),\n path: z.string(),\n locale: z.string(),\n title: z.string().nullable(),\n description: z.string().nullable(),\n isPublished: z.boolean(),\n isPrivate: z.boolean(),\n tags: z.array(z.string()),\n createdAt: z.string(),\n updatedAt: z.string(),\n};\n\nexport function registerDiscoveryTools(\n server: McpServer,\n wiki: WikiJsClient,\n logger: Logger,\n): void {\n server.registerTool(\n 'search_pages',\n {\n title: 'Search pages',\n description:\n 'Full-text search Wiki.js pages. Returns matching pages with id, title, path and locale. Use get_page to fetch content.',\n inputSchema: {\n query: z.string().min(1).describe('Search keywords'),\n path: z.string().optional().describe('Restrict results to this path prefix'),\n locale: z.string().optional().describe('Locale code, e.g. \"en\"'),\n },\n outputSchema: {\n results: z.array(\n z.object({\n id: z.string(),\n title: z.string(),\n description: z.string(),\n path: z.string(),\n locale: z.string(),\n }),\n ),\n suggestions: z.array(z.string()),\n totalHits: z.number(),\n },\n },\n instrument(logger, 'search_pages', async (args) => {\n try {\n return ok(await wiki.searchPages(args));\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'list_pages',\n {\n title: 'List pages',\n description: 'List Wiki.js pages with optional ordering, tag and locale filters.',\n inputSchema: {\n limit: z.number().int().min(1).max(500).default(50).describe('Max pages to return'),\n orderBy: z.enum(['CREATED', 'ID', 'PATH', 'TITLE', 'UPDATED']).optional(),\n orderByDirection: z.enum(['ASC', 'DESC']).optional(),\n tags: z.array(z.string()).optional().describe('Only pages having all these tags'),\n locale: z.string().optional(),\n },\n outputSchema: {\n pages: z.array(z.object({ ...pageSummaryShape, contentType: z.string() })),\n total: z.number(),\n },\n },\n instrument(logger, 'list_pages', async (args) => {\n try {\n const pages = await wiki.listPages(args);\n return ok({\n pages: pages.map((p) => ({\n ...p,\n title: p.title ?? null,\n description: p.description ?? null,\n })),\n total: pages.length,\n });\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'get_page',\n {\n title: 'Get page',\n description:\n 'Fetch one page by numeric id OR by path (+ locale, default \"en\"). ' +\n 'Optionally slice its content by line range with startLine/endLine: 0-based, ' +\n 'inclusive on both ends. Default (0..-1) returns the whole page. Negative values ' +\n 'count from the end, Python-style (-1 = last line, -2 = second-to-last).',\n inputSchema: {\n id: z.number().int().optional().describe('Page id (preferred when known)'),\n path: z.string().optional().describe('Page path, e.g. \"guides/install\"'),\n locale: z.string().default('en').describe('Locale for path lookup'),\n startLine: z\n .number()\n .int()\n .default(0)\n .describe('0-based start line, inclusive. Negative counts from the end.'),\n endLine: z\n .number()\n .int()\n .default(-1)\n .describe('0-based end line, inclusive. -1 (default) means the last line.'),\n },\n outputSchema: {\n page: z.object({\n id: z.number(),\n path: z.string(),\n locale: z.string(),\n title: z.string(),\n description: z.string(),\n content: z.string(),\n contentType: z.string(),\n editor: z.string(),\n isPublished: z.boolean(),\n isPrivate: z.boolean(),\n tags: z.array(z.string()),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n totalLines: z.number(),\n startLine: z.number(),\n endLine: z.number(),\n },\n },\n instrument(logger, 'get_page', async (args) => {\n try {\n if (args.id == null && !args.path) {\n return fail(new Error('Provide either \"id\" or \"path\"'));\n }\n const page =\n args.id != null\n ? await wiki.getPageById(args.id)\n : await wiki.getPageByPath(args.path as string, args.locale);\n if (!page) {\n return fail(\n new Error(\n `Page not found: ${args.id != null ? `id ${args.id}` : `${args.locale}/${args.path as string}`}`,\n ),\n );\n }\n\n const sliced = sliceLines(page.content, args.startLine, args.endLine);\n\n return ok({\n page: { ...page, content: sliced.content },\n totalLines: sliced.totalLines,\n startLine: sliced.startLine,\n endLine: sliced.endLine,\n });\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'get_page_tree',\n {\n title: 'Browse page tree',\n description:\n 'Browse the page/folder hierarchy one level at a time. Omit parent for the root level; pass a folder item id as parent to descend.',\n inputSchema: {\n parent: z\n .number()\n .int()\n .optional()\n .describe('Tree item id to list children of (omit for root)'),\n mode: z.enum(['ALL', 'PAGES', 'FOLDERS']).default('ALL'),\n locale: z.string().default('en'),\n includeAncestors: z.boolean().optional(),\n },\n outputSchema: {\n items: z.array(\n z.object({\n id: z.number(),\n path: z.string(),\n depth: z.number(),\n title: z.string(),\n isFolder: z.boolean(),\n pageId: z.number().nullable(),\n parent: z.number().nullable(),\n locale: z.string(),\n }),\n ),\n },\n },\n instrument(logger, 'get_page_tree', async (args) => {\n try {\n const items = await wiki.getTree({ ...args, parent: args.parent ?? 0 });\n return ok({\n items: items.map((i) => ({ ...i, pageId: i.pageId ?? null, parent: i.parent ?? null })),\n });\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'list_tags',\n {\n title: 'List tags',\n description: 'List all page tags, or search tags matching a query string.',\n inputSchema: {\n query: z.string().optional().describe('If set, search tags matching this text'),\n },\n outputSchema: {\n tags: z.array(z.object({ tag: z.string(), title: z.string().nullable() })),\n },\n },\n instrument(logger, 'list_tags', async (args) => {\n try {\n if (args.query) {\n const tags = await wiki.searchTags(args.query);\n return ok({ tags: tags.map((t) => ({ tag: t, title: null })) });\n }\n const tags = await wiki.listTags();\n return ok({ tags: tags.map((t) => ({ tag: t.tag, title: t.title ?? null })) });\n } catch (err) {\n return fail(err);\n }\n }),\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { WikiJsClient } from '../client/wikijs.ts';\nimport type { Logger } from '../logger.ts';\nimport { ok, fail, instrument } from './result.ts';\n\nconst pageRefShape = {\n id: z.number(),\n path: z.string(),\n locale: z.string(),\n title: z.string(),\n};\n\nexport function registerPageTools(server: McpServer, wiki: WikiJsClient, logger: Logger): void {\n server.registerTool(\n 'create_page',\n {\n title: 'Create page',\n description:\n 'Create a new Wiki.js page. Path must not start with the locale (use \"guides/install\", not \"en/guides/install\").',\n inputSchema: {\n path: z.string().min(1).describe('Page path, e.g. \"guides/install\"'),\n title: z.string().min(1),\n content: z.string().min(1).describe('Page content (markdown by default)'),\n description: z.string().default('').describe('Short page description'),\n editor: z.string().default('markdown').describe('Editor type: markdown, ckeditor, code'),\n locale: z.string().default('en'),\n isPublished: z.boolean().default(true),\n isPrivate: z.boolean().default(false),\n tags: z.array(z.string()).default([]),\n },\n outputSchema: {\n succeeded: z.literal(true),\n page: z.object(pageRefShape),\n },\n },\n instrument(logger, 'create_page', async (args) => {\n try {\n const page = await wiki.createPage(args);\n return ok(\n { succeeded: true as const, page },\n `Created page ${page.id} at ${page.locale}/${page.path}`,\n );\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'update_page',\n {\n title: 'Update page',\n description:\n 'Update an existing page by id. Only the provided fields change. Get the id from get_page, list_pages or search_pages first.',\n inputSchema: {\n id: z.number().int().describe('Page id'),\n content: z.string().optional(),\n title: z.string().optional(),\n description: z.string().optional(),\n isPublished: z.boolean().optional(),\n isPrivate: z.boolean().optional(),\n tags: z.array(z.string()).optional().describe('Replaces the whole tag list'),\n },\n outputSchema: {\n succeeded: z.literal(true),\n page: z.object(pageRefShape),\n },\n },\n instrument(logger, 'update_page', async (args) => {\n try {\n const page = await wiki.updatePage(args);\n return ok(\n { succeeded: true as const, page },\n `Updated page ${page.id} at ${page.locale}/${page.path}`,\n );\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'move_page',\n {\n title: 'Move / rename page',\n description:\n 'Move a page to a new path (and optionally another locale). Requires the manage:pages permission on the API key.',\n inputSchema: {\n id: z.number().int().describe('Page id'),\n destinationPath: z.string().min(1),\n destinationLocale: z.string().default('en'),\n },\n outputSchema: {\n succeeded: z.literal(true),\n id: z.number(),\n destinationPath: z.string(),\n destinationLocale: z.string(),\n },\n },\n instrument(logger, 'move_page', async (args) => {\n try {\n await wiki.movePage(args.id, args.destinationPath, args.destinationLocale);\n return ok(\n {\n succeeded: true as const,\n id: args.id,\n destinationPath: args.destinationPath,\n destinationLocale: args.destinationLocale,\n },\n `Moved page ${args.id} to ${args.destinationLocale}/${args.destinationPath}`,\n );\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'delete_page',\n {\n title: 'Delete page',\n description:\n 'Permanently delete a page by id. DESTRUCTIVE and irreversible — confirm with the user before calling this.',\n inputSchema: {\n id: z.number().int().describe('Page id to delete'),\n },\n outputSchema: {\n succeeded: z.literal(true),\n id: z.number(),\n },\n },\n instrument(logger, 'delete_page', async (args) => {\n try {\n await wiki.deletePage(args.id);\n return ok({ succeeded: true as const, id: args.id }, `Deleted page ${args.id}`);\n } catch (err) {\n return fail(err);\n }\n }),\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { WikiJsClient } from '../client/wikijs.ts';\nimport type { Logger } from '../logger.ts';\nimport { ok, fail, instrument, sliceLines } from './result.ts';\n\nexport function registerHistoryTools(server: McpServer, wiki: WikiJsClient, logger: Logger): void {\n server.registerTool(\n 'get_page_history',\n {\n title: 'Get page history',\n description: 'List the version history trail of a page (newest first), paginated.',\n inputSchema: {\n id: z.number().int().describe('Page id'),\n offsetPage: z.number().int().min(0).default(0).describe('Zero-based page of the trail'),\n offsetSize: z.number().int().min(1).max(100).default(25).describe('Entries per page'),\n },\n outputSchema: {\n trail: z.array(\n z.object({\n versionId: z.number(),\n versionDate: z.string(),\n authorId: z.number(),\n authorName: z.string(),\n actionType: z.string(),\n valueBefore: z.string().nullable(),\n valueAfter: z.string().nullable(),\n }),\n ),\n total: z.number(),\n },\n },\n instrument(logger, 'get_page_history', async (args) => {\n try {\n const history = await wiki.getHistory(args.id, args.offsetPage, args.offsetSize);\n return ok({\n trail: history.trail.map((e) => ({\n ...e,\n valueBefore: e.valueBefore ?? null,\n valueAfter: e.valueAfter ?? null,\n })),\n total: history.total,\n });\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'get_page_version',\n {\n title: 'Get page version',\n description:\n 'Fetch the content of a specific historical version of a page. Optionally slice ' +\n 'its content by line range with startLine/endLine: 0-based, inclusive on both ends. ' +\n 'Default (0..-1) returns the whole version content. Negative values count from the ' +\n 'end, Python-style (-1 = last line, -2 = second-to-last).',\n inputSchema: {\n pageId: z.number().int(),\n versionId: z.number().int().describe('From get_page_history trail'),\n startLine: z\n .number()\n .int()\n .default(0)\n .describe('0-based start line, inclusive. Negative counts from the end.'),\n endLine: z\n .number()\n .int()\n .default(-1)\n .describe('0-based end line, inclusive. -1 (default) means the last line.'),\n },\n outputSchema: {\n version: z.object({\n versionId: z.number(),\n versionDate: z.string(),\n action: z.string(),\n authorName: z.string(),\n pageId: z.number(),\n path: z.string(),\n locale: z.string(),\n title: z.string(),\n description: z.string(),\n content: z.string(),\n contentType: z.string(),\n editor: z.string(),\n isPublished: z.boolean(),\n tags: z.array(z.string()),\n createdAt: z.string(),\n }),\n totalLines: z.number(),\n startLine: z.number(),\n endLine: z.number(),\n },\n },\n instrument(logger, 'get_page_version', async (args) => {\n try {\n const version = await wiki.getVersion(args.pageId, args.versionId);\n const sliced = sliceLines(version.content, args.startLine, args.endLine);\n\n return ok({\n version: { ...version, content: sliced.content },\n totalLines: sliced.totalLines,\n startLine: sliced.startLine,\n endLine: sliced.endLine,\n });\n } catch (err) {\n return fail(err);\n }\n }),\n );\n\n server.registerTool(\n 'restore_page_version',\n {\n title: 'Restore page version',\n description:\n 'Restore a page to a previous version from its history. The current state is preserved as a new history entry.',\n inputSchema: {\n pageId: z.number().int(),\n versionId: z.number().int().describe('Version to restore, from get_page_history'),\n },\n outputSchema: {\n succeeded: z.literal(true),\n pageId: z.number(),\n versionId: z.number(),\n },\n },\n instrument(logger, 'restore_page_version', async (args) => {\n try {\n await wiki.restoreVersion(args.pageId, args.versionId);\n return ok(\n { succeeded: true as const, pageId: args.pageId, versionId: args.versionId },\n `Restored page ${args.pageId} to version ${args.versionId}`,\n );\n } catch (err) {\n return fail(err);\n }\n }),\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { WikiJsClient } from '../client/wikijs.ts';\nimport type { Logger } from '../logger.ts';\nimport { ok, fail, instrument } from './result.ts';\n\nexport function registerAssetTools(server: McpServer, wiki: WikiJsClient, logger: Logger): void {\n server.registerTool(\n 'list_assets',\n {\n title: 'List assets',\n description:\n 'List uploaded assets (images/files) and subfolders in an asset folder. folderId 0 is the root folder.',\n inputSchema: {\n folderId: z.number().int().min(0).default(0),\n kind: z.enum(['IMAGE', 'BINARY', 'ALL']).default('ALL'),\n },\n outputSchema: {\n folders: z.array(\n z.object({ id: z.number(), slug: z.string(), name: z.string().nullable() }),\n ),\n assets: z.array(\n z.object({\n id: z.number(),\n filename: z.string(),\n ext: z.string(),\n kind: z.string(),\n mime: z.string(),\n fileSize: z.number(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n ),\n },\n },\n instrument(logger, 'list_assets', async (args) => {\n try {\n const [folders, assets] = await Promise.all([\n wiki.listAssetFolders(args.folderId),\n wiki.listAssets(args.folderId, args.kind),\n ]);\n return ok({\n folders: folders.map((f) => ({ ...f, name: f.name ?? null })),\n assets,\n });\n } catch (err) {\n return fail(err);\n }\n }),\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport pkg from '../package.json' with { type: 'json' };\nimport type { Config } from './config.ts';\nimport type { Logger } from './logger.ts';\nimport { GraphQLClient } from './client/graphql.ts';\nimport { WikiJsClient } from './client/wikijs.ts';\nimport { registerDiscoveryTools } from './tools/discovery.ts';\nimport { registerPageTools } from './tools/pages.ts';\nimport { registerHistoryTools } from './tools/history.ts';\nimport { registerAssetTools } from './tools/assets.ts';\n\nexport const VERSION = pkg.version;\n\nexport function buildServer(config: Config, logger: Logger): McpServer {\n const wiki = new WikiJsClient(\n new GraphQLClient({ baseUrl: config.wikijsUrl, token: config.wikijsToken }),\n );\n const server = new McpServer({ name: 'wikijs-mcp', version: VERSION });\n registerDiscoveryTools(server, wiki, logger);\n registerPageTools(server, wiki, logger);\n registerHistoryTools(server, wiki, logger);\n registerAssetTools(server, wiki, logger);\n logger.debug('MCP server built');\n return server;\n}\n\nexport async function probeConnection(config: Config, logger: Logger): Promise<void> {\n const wiki = new WikiJsClient(\n new GraphQLClient({ baseUrl: config.wikijsUrl, token: config.wikijsToken, timeoutMs: 10_000 }),\n );\n try {\n await wiki.listPages({ limit: 1 });\n logger.info({ url: config.wikijsUrl }, 'Connected to Wiki.js');\n } catch (err) {\n logger.warn(\n { url: config.wikijsUrl, err: (err as Error).message },\n 'Wiki.js connectivity check failed — starting anyway',\n );\n }\n}\n","#!/usr/bin/env node\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from './config.ts';\nimport { createLogger } from './logger.ts';\nimport { buildServer, probeConnection } from './server.ts';\n\nasync function main(): Promise<void> {\n const config = loadConfig();\n const logger = createLogger(config.logLevel);\n\n await probeConnection(config, logger);\n\n if (config.transport === 'http') {\n const { startHttpServer } = await import('./http.ts');\n startHttpServer(config, logger);\n return;\n }\n\n const server = buildServer(config, logger);\n await server.connect(new StdioServerTransport());\n logger.info('wikijs-mcp listening on stdio');\n}\n\nmain().catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@sondt2709/wikijs-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for managing Wiki.js pages — search, read, create, update, move, delete, history, assets",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/sondt2709/wikijs-mcp.git"
9
+ },
10
+ "keywords": [
11
+ "mcp",
12
+ "model-context-protocol",
13
+ "wikijs",
14
+ "wiki.js",
15
+ "wiki",
16
+ "ai"
17
+ ],
18
+ "type": "module",
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "bin": {
23
+ "wikijs-mcp": "dist/index.js"
24
+ },
25
+ "main": "dist/index.js",
26
+ "files": [
27
+ "dist",
28
+ "README.md",
29
+ "LICENSE"
30
+ ],
31
+ "engines": {
32
+ "node": ">=22.18"
33
+ },
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.29.0",
36
+ "pino": "^10.3.1",
37
+ "zod": "^4.4.3"
38
+ },
39
+ "devDependencies": {
40
+ "@eslint/js": "^10.0.1",
41
+ "@types/node": "^22.20.0",
42
+ "eslint": "^10.6.0",
43
+ "lefthook": "^2.1.9",
44
+ "prettier": "^3.9.4",
45
+ "tsdown": "^0.22.3",
46
+ "typescript": "^6.0.3",
47
+ "typescript-eslint": "^8.62.1",
48
+ "vitest": "^4.1.9"
49
+ },
50
+ "scripts": {
51
+ "dev": "node --watch --env-file-if-exists=.env src/index.ts",
52
+ "build": "tsdown",
53
+ "typecheck": "tsc --noEmit",
54
+ "lint": "eslint .",
55
+ "format": "prettier --write .",
56
+ "format:check": "prettier --check .",
57
+ "test:e2e": "pnpm build && vitest run",
58
+ "inspect": "pnpm build && npx @modelcontextprotocol/inspector node dist/index.js",
59
+ "e2e:wiki:up": "docker compose -f e2e/docker/compose.yaml up -d --wait",
60
+ "e2e:wiki:down": "docker compose -f e2e/docker/compose.yaml down -v",
61
+ "e2e:bootstrap": "node e2e/scripts/bootstrap.ts"
62
+ }
63
+ }