feat: Add 22 new tools for complete Outline coverage (v1.1.0)
New modules (22 tools): - Stars (3): list, create, delete - bookmarks - Pins (3): list, create, delete - highlighted docs - Views (2): list, create - view tracking - Reactions (3): list, create, delete - emoji on comments - API Keys (4): list, create, update, delete - Webhooks (4): list, create, update, delete - Backlinks (1): list - read-only view - Search Queries (2): list, stats - analytics Total tools: 86 -> 108 (+22) All 22 new tools validated against Outline v0.78 schema. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
99
src/tools/backlinks.ts
Normal file
99
src/tools/backlinks.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* MCP Outline PostgreSQL - Backlinks Tools
|
||||
* Note: backlinks is a VIEW, not a table - read-only
|
||||
* @author Descomplicar® | @link descomplicar.pt | @copyright 2026
|
||||
*/
|
||||
|
||||
import { Pool } from 'pg';
|
||||
import { BaseTool, ToolResponse, PaginationArgs } from '../types/tools.js';
|
||||
import { validatePagination, isValidUUID } from '../utils/security.js';
|
||||
|
||||
interface BacklinkListArgs extends PaginationArgs {
|
||||
document_id?: string;
|
||||
reverse_document_id?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* backlinks.list - List document backlinks
|
||||
*/
|
||||
const listBacklinks: BaseTool<BacklinkListArgs> = {
|
||||
name: 'outline_backlinks_list',
|
||||
description: 'List backlinks between documents. Shows which documents link to which. Backlinks is a view (read-only).',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
document_id: {
|
||||
type: 'string',
|
||||
description: 'Filter by source document ID (UUID) - documents that link TO this',
|
||||
},
|
||||
reverse_document_id: {
|
||||
type: 'string',
|
||||
description: 'Filter by target document ID (UUID) - documents that ARE LINKED FROM this',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum results (default: 25, max: 100)',
|
||||
},
|
||||
offset: {
|
||||
type: 'number',
|
||||
description: 'Results to skip (default: 0)',
|
||||
},
|
||||
},
|
||||
},
|
||||
handler: async (args, pgClient): Promise<ToolResponse> => {
|
||||
const { limit, offset } = validatePagination(args.limit, args.offset);
|
||||
const conditions: string[] = [];
|
||||
const params: any[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
if (args.document_id) {
|
||||
if (!isValidUUID(args.document_id)) throw new Error('Invalid document_id format');
|
||||
conditions.push(`b."documentId" = $${paramIndex++}`);
|
||||
params.push(args.document_id);
|
||||
}
|
||||
|
||||
if (args.reverse_document_id) {
|
||||
if (!isValidUUID(args.reverse_document_id)) throw new Error('Invalid reverse_document_id format');
|
||||
conditions.push(`b."reverseDocumentId" = $${paramIndex++}`);
|
||||
params.push(args.reverse_document_id);
|
||||
}
|
||||
|
||||
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
||||
|
||||
const result = await pgClient.query(
|
||||
`
|
||||
SELECT
|
||||
b.id,
|
||||
b."documentId",
|
||||
b."reverseDocumentId",
|
||||
b."userId",
|
||||
b."createdAt",
|
||||
b."updatedAt",
|
||||
d.title as "documentTitle",
|
||||
rd.title as "reverseDocumentTitle",
|
||||
u.name as "userName"
|
||||
FROM backlinks b
|
||||
LEFT JOIN documents d ON b."documentId" = d.id
|
||||
LEFT JOIN documents rd ON b."reverseDocumentId" = rd.id
|
||||
LEFT JOIN users u ON b."userId" = u.id
|
||||
${whereClause}
|
||||
ORDER BY b."createdAt" DESC
|
||||
LIMIT $${paramIndex++} OFFSET $${paramIndex}
|
||||
`,
|
||||
[...params, limit, offset]
|
||||
);
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: 'text',
|
||||
text: JSON.stringify({
|
||||
data: result.rows,
|
||||
pagination: { limit, offset, total: result.rows.length },
|
||||
note: 'Backlinks is a read-only view. Links are automatically detected from document content.',
|
||||
}, null, 2),
|
||||
}],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const backlinksTools: BaseTool<any>[] = [listBacklinks];
|
||||
Reference in New Issue
Block a user