Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 2s
Monorepo Pipeline / 🧪 Test (push) Successful in 1m56s
Monorepo Pipeline / 🧹 Lint (push) Failing after 3m24s
Monorepo Pipeline / 🏗️ Build (push) Successful in 4m11s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
185 lines
5.3 KiB
TypeScript
185 lines
5.3 KiB
TypeScript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
import {
|
|
CallToolRequestSchema,
|
|
ListToolsRequestSchema,
|
|
Tool,
|
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
import axios from "axios";
|
|
|
|
// Environment variables
|
|
const OUTLINE_API_TOKEN = process.env.OUTLINE_API_TOKEN;
|
|
const OUTLINE_BASE_URL = process.env.OUTLINE_BASE_URL;
|
|
|
|
if (!OUTLINE_API_TOKEN || !OUTLINE_BASE_URL) {
|
|
console.error("Missing required environment variables: OUTLINE_API_TOKEN or OUTLINE_BASE_URL");
|
|
process.exit(1);
|
|
}
|
|
|
|
const axiosInstance = axios.create({
|
|
baseURL: OUTLINE_BASE_URL,
|
|
headers: {
|
|
Authorization: `Bearer ${OUTLINE_API_TOKEN}`,
|
|
"Content-Type": "application/json",
|
|
Accept: "application/json",
|
|
},
|
|
});
|
|
|
|
// Define tools
|
|
const tools: Tool[] = [
|
|
{
|
|
name: "outline_search_documents",
|
|
description: "Search for documents in Outline.",
|
|
inputSchema: {
|
|
type: "object",
|
|
properties: {
|
|
query: { type: "string", description: "Search query" },
|
|
collectionId: { type: "string", description: "Optional collection ID to scope search" },
|
|
},
|
|
required: ["query"],
|
|
},
|
|
},
|
|
{
|
|
name: "outline_get_document",
|
|
description: "Get a document by its ID.",
|
|
inputSchema: {
|
|
type: "object",
|
|
properties: {
|
|
id: { type: "string", description: "The ID of the document" },
|
|
},
|
|
required: ["id"],
|
|
},
|
|
},
|
|
{
|
|
name: "outline_create_document",
|
|
description: "Create a new document.",
|
|
inputSchema: {
|
|
type: "object",
|
|
properties: {
|
|
collectionId: { type: "string", description: "The ID of the collection" },
|
|
title: { type: "string", description: "Document title" },
|
|
text: { type: "string", description: "Document content in Markdown" },
|
|
publish: { type: "boolean", description: "Whether to publish the document" },
|
|
},
|
|
required: ["collectionId", "title", "text"],
|
|
},
|
|
},
|
|
{
|
|
name: "outline_update_document",
|
|
description: "Update an existing document.",
|
|
inputSchema: {
|
|
type: "object",
|
|
properties: {
|
|
id: { type: "string", description: "The ID of the document" },
|
|
title: { type: "string", description: "New title" },
|
|
text: { type: "string", description: "New content in Markdown" },
|
|
},
|
|
required: ["id"],
|
|
},
|
|
},
|
|
{
|
|
name: "outline_create_collection",
|
|
description: "Create a new collection.",
|
|
inputSchema: {
|
|
type: "object",
|
|
properties: {
|
|
name: { type: "string", description: "Collection name" },
|
|
description: { type: "string", description: "Collection description" },
|
|
},
|
|
required: ["name"],
|
|
},
|
|
},
|
|
];
|
|
|
|
const server = new Server(
|
|
{
|
|
name: "at-mintel-outline-mcp",
|
|
version: "1.0.0",
|
|
},
|
|
{
|
|
capabilities: {
|
|
tools: {},
|
|
},
|
|
}
|
|
);
|
|
|
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
return { tools };
|
|
});
|
|
|
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
try {
|
|
switch (request.params.name) {
|
|
case "outline_search_documents": {
|
|
const { query, collectionId } = request.params.arguments as any;
|
|
const res = await axiosInstance.post("/api/documents.search", {
|
|
query,
|
|
collectionId,
|
|
});
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
};
|
|
}
|
|
case "outline_get_document": {
|
|
const { id } = request.params.arguments as any;
|
|
const res = await axiosInstance.post("/api/documents.info", { id });
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
};
|
|
}
|
|
case "outline_create_document": {
|
|
const { collectionId, title, text, publish } = request.params.arguments as any;
|
|
const res = await axiosInstance.post("/api/documents.create", {
|
|
collectionId,
|
|
title,
|
|
text,
|
|
publish: publish ?? true,
|
|
});
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
};
|
|
}
|
|
case "outline_update_document": {
|
|
const { id, title, text } = request.params.arguments as any;
|
|
const res = await axiosInstance.post("/api/documents.update", {
|
|
id,
|
|
title,
|
|
text,
|
|
});
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
};
|
|
}
|
|
case "outline_create_collection": {
|
|
const { name, description } = request.params.arguments as any;
|
|
const res = await axiosInstance.post("/api/collections.create", {
|
|
name,
|
|
description,
|
|
});
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }],
|
|
};
|
|
}
|
|
default:
|
|
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
}
|
|
} catch (error: any) {
|
|
const errorMsg = error.response?.data ? JSON.stringify(error.response.data) : error.message;
|
|
return {
|
|
content: [{ type: "text", text: `API Error: ${errorMsg}` }],
|
|
isError: true,
|
|
};
|
|
}
|
|
});
|
|
|
|
async function main() {
|
|
const transport = new StdioServerTransport();
|
|
await server.connect(transport);
|
|
console.error("Outline MCP Server running on stdio");
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error("Fatal error:", error);
|
|
process.exit(1);
|
|
});
|