fix(critical): Create revision on document creation
Documents created via MCP were not visible in Outline interface. Outline requires an entry in the revisions table to display documents. Now uses transaction to insert into both documents and revisions tables. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -2,6 +2,16 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [1.3.9] - 2026-01-31
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Document Visibility (Critical):** `create_document` now creates initial revision
|
||||||
|
- Was: Documents created via MCP didn't appear in Outline interface
|
||||||
|
- Cause: Outline requires entry in `revisions` table to display documents
|
||||||
|
- Now: Uses transaction to insert into both `documents` and `revisions` tables
|
||||||
|
- Documents created via MCP now visible immediately in Outline
|
||||||
|
|
||||||
## [1.3.8] - 2026-01-31
|
## [1.3.8] - 2026-01-31
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
MCP server for direct PostgreSQL access to Outline Wiki database. Follows patterns established by `mcp-desk-crm-sql-v3`.
|
MCP server for direct PostgreSQL access to Outline Wiki database. Follows patterns established by `mcp-desk-crm-sql-v3`.
|
||||||
|
|
||||||
**Version:** 1.3.8
|
**Version:** 1.3.9
|
||||||
**Total Tools:** 164 tools across 33 modules
|
**Total Tools:** 164 tools across 33 modules
|
||||||
**Production:** hub.descomplicar.pt (via SSH tunnel)
|
**Production:** hub.descomplicar.pt (via SSH tunnel)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# MCP Outline PostgreSQL - Continuacao de Testes
|
# MCP Outline PostgreSQL - Continuacao de Testes
|
||||||
|
|
||||||
**Ultima Sessao:** 2026-01-31 (actualizado)
|
**Ultima Sessao:** 2026-01-31 (actualizado)
|
||||||
**Versao Actual:** 1.3.8
|
**Versao Actual:** 1.3.9
|
||||||
**Progresso:** ~95/164 tools testadas (58%) - **CÓDIGO VALIDADO**
|
**Progresso:** ~95/164 tools testadas (58%) - **CÓDIGO VALIDADO**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "mcp-outline-postgresql",
|
"name": "mcp-outline-postgresql",
|
||||||
"version": "1.3.8",
|
"version": "1.3.9",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "mcp-outline-postgresql",
|
"name": "mcp-outline-postgresql",
|
||||||
"version": "1.3.8",
|
"version": "1.3.9",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.0.0",
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mcp-outline-postgresql",
|
"name": "mcp-outline-postgresql",
|
||||||
"version": "1.3.8",
|
"version": "1.3.9",
|
||||||
"description": "MCP Server for Outline Wiki via PostgreSQL direct access",
|
"description": "MCP Server for Outline Wiki via PostgreSQL direct access",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ async function main() {
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
transport: 'streamable-http',
|
transport: 'streamable-http',
|
||||||
version: '1.3.8',
|
version: '1.3.9',
|
||||||
sessions: sessions.size,
|
sessions: sessions.size,
|
||||||
stateful: STATEFUL,
|
stateful: STATEFUL,
|
||||||
tools: allTools.length
|
tools: allTools.length
|
||||||
@@ -101,7 +101,7 @@ async function main() {
|
|||||||
// Create MCP server
|
// Create MCP server
|
||||||
const server = createMcpServer(pgClient.getPool(), {
|
const server = createMcpServer(pgClient.getPool(), {
|
||||||
name: 'mcp-outline-http',
|
name: 'mcp-outline-http',
|
||||||
version: '1.3.8'
|
version: '1.3.9'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Track session if stateful
|
// Track session if stateful
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ async function main() {
|
|||||||
// Create MCP server with shared configuration
|
// Create MCP server with shared configuration
|
||||||
const server = createMcpServer(pgClient.getPool(), {
|
const server = createMcpServer(pgClient.getPool(), {
|
||||||
name: 'mcp-outline-postgresql',
|
name: 'mcp-outline-postgresql',
|
||||||
version: '1.3.8'
|
version: '1.3.9'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Connect stdio transport
|
// Connect stdio transport
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ export function createMcpServer(
|
|||||||
): Server {
|
): Server {
|
||||||
const server = new Server({
|
const server = new Server({
|
||||||
name: config.name || 'mcp-outline-postgresql',
|
name: config.name || 'mcp-outline-postgresql',
|
||||||
version: config.version || '1.3.8'
|
version: config.version || '1.3.9'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set capabilities (required for MCP v2.2+)
|
// Set capabilities (required for MCP v2.2+)
|
||||||
|
|||||||
@@ -236,7 +236,11 @@ const createDocument: BaseTool<CreateDocumentArgs> = {
|
|||||||
);
|
);
|
||||||
const teamId = teamResult.rows[0]?.teamId;
|
const teamId = teamResult.rows[0]?.teamId;
|
||||||
|
|
||||||
const query = `
|
// Use transaction to ensure both document and revision are created
|
||||||
|
await pgClient.query('BEGIN');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const docQuery = `
|
||||||
INSERT INTO documents (
|
INSERT INTO documents (
|
||||||
id, "urlId", title, text, "collectionId", "teamId", "parentDocumentId", "createdById",
|
id, "urlId", title, text, "collectionId", "teamId", "parentDocumentId", "createdById",
|
||||||
"lastModifiedById", template, "publishedAt", "createdAt", "updatedAt", version,
|
"lastModifiedById", template, "publishedAt", "createdAt", "updatedAt", version,
|
||||||
@@ -250,7 +254,7 @@ const createDocument: BaseTool<CreateDocumentArgs> = {
|
|||||||
RETURNING id, "urlId", title, "collectionId", "publishedAt", "createdAt"
|
RETURNING id, "urlId", title, "collectionId", "publishedAt", "createdAt"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const params = [
|
const docParams = [
|
||||||
title,
|
title,
|
||||||
text,
|
text,
|
||||||
args.collection_id,
|
args.collection_id,
|
||||||
@@ -262,18 +266,43 @@ const createDocument: BaseTool<CreateDocumentArgs> = {
|
|||||||
publishedAt
|
publishedAt
|
||||||
];
|
];
|
||||||
|
|
||||||
const result = await pgClient.query(query, params);
|
const docResult = await pgClient.query(docQuery, docParams);
|
||||||
|
const newDoc = docResult.rows[0];
|
||||||
|
|
||||||
|
// Insert initial revision (required for Outline to display the document)
|
||||||
|
const revisionQuery = `
|
||||||
|
INSERT INTO revisions (
|
||||||
|
id, "documentId", "userId", title, text,
|
||||||
|
"createdAt", "updatedAt"
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
gen_random_uuid(), $1, $2, $3, $4, NOW(), NOW()
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
|
||||||
|
await pgClient.query(revisionQuery, [
|
||||||
|
newDoc.id,
|
||||||
|
userId,
|
||||||
|
title,
|
||||||
|
text
|
||||||
|
]);
|
||||||
|
|
||||||
|
await pgClient.query('COMMIT');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [{
|
content: [{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: JSON.stringify({
|
text: JSON.stringify({
|
||||||
success: true,
|
success: true,
|
||||||
document: result.rows[0],
|
document: newDoc,
|
||||||
message: args.publish ? 'Documento criado e publicado' : 'Draft criado (não publicado)'
|
message: args.publish ? 'Documento criado e publicado' : 'Draft criado (não publicado)'
|
||||||
}, null, 2)
|
}, null, 2)
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
} catch (txError) {
|
||||||
|
await pgClient.query('ROLLBACK');
|
||||||
|
throw txError;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
content: [{
|
content: [{
|
||||||
|
|||||||
Reference in New Issue
Block a user