outline-mcp-server 5.4.0 → 5.5.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.
- package/README.md +32 -3
- package/build/index.js +65 -10
- package/build/outline/outlineClient.js +47 -10
- package/build/stdio.js +5 -0
- package/build/tools/archiveDocument.js +3 -2
- package/build/tools/askDocuments.js +3 -2
- package/build/tools/createCollection.js +3 -2
- package/build/tools/createComment.js +3 -2
- package/build/tools/createDocument.js +3 -2
- package/build/tools/createTemplateFromDocument.js +3 -2
- package/build/tools/deleteComment.js +3 -2
- package/build/tools/deleteDocument.js +3 -2
- package/build/tools/getCollection.js +3 -2
- package/build/tools/getDocument.js +3 -2
- package/build/tools/listCollections.js +3 -2
- package/build/tools/listDocuments.js +3 -2
- package/build/tools/listUsers.js +3 -2
- package/build/tools/moveDocument.js +3 -2
- package/build/tools/searchDocuments.js +3 -2
- package/build/tools/updateCollection.js +3 -2
- package/build/tools/updateComment.js +3 -2
- package/build/tools/updateDocument.js +3 -2
- package/build/utils/toolRegistry.js +31 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,13 +59,18 @@ One click install in Cursor:
|
|
|
59
59
|
`outline-mcp-server` supports the latest streamable-http protocol, the deprecated sse protocol, and good ole fashioned stdio.
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
# S-HTTP/SSE servers
|
|
62
|
+
# S-HTTP/SSE servers (with optional env var)
|
|
63
63
|
OUTLINE_API_KEY=... npx -y outline-mcp-server@latest
|
|
64
64
|
|
|
65
|
-
#
|
|
65
|
+
# S-HTTP/SSE servers (without env var, use headers for auth)
|
|
66
|
+
npx -y outline-mcp-server@latest
|
|
67
|
+
|
|
68
|
+
# STDIO (requires env var)
|
|
66
69
|
OUTLINE_API_KEY=... npx -y --package=outline-mcp-server@latest -c outline-mcp-server-stdio
|
|
67
70
|
```
|
|
68
71
|
|
|
72
|
+
When running HTTP/SSE servers without an environment variable, you'll need to provide the API key in your request headers. The server will display available authentication methods on startup.
|
|
73
|
+
|
|
69
74
|
### Cursor (mcp.json)
|
|
70
75
|
|
|
71
76
|
Add the following MCP definition to your configuration:
|
|
@@ -85,9 +90,33 @@ Add the following MCP definition to your configuration:
|
|
|
85
90
|
}
|
|
86
91
|
```
|
|
87
92
|
|
|
93
|
+
### Authentication
|
|
94
|
+
|
|
95
|
+
The Outline MCP server supports two authentication methods:
|
|
96
|
+
|
|
97
|
+
1. **Environment Variable (Required for stdio mode)**: Set `OUTLINE_API_KEY` as an environment variable
|
|
98
|
+
2. **Request Headers (HTTP/SSE modes)**: Provide the API key in request headers
|
|
99
|
+
|
|
100
|
+
For **stdio mode**, the API key environment variable is required and validated on startup.
|
|
101
|
+
|
|
102
|
+
For **HTTP/SSE modes**, you have two options:
|
|
103
|
+
|
|
104
|
+
- Set `OUTLINE_API_KEY` as an environment variable (fallback method)
|
|
105
|
+
- Provide API key in request headers (recommended for per-request authentication)
|
|
106
|
+
|
|
107
|
+
#### Header-based Authentication
|
|
108
|
+
|
|
109
|
+
When using HTTP/SSE endpoints, you can provide the API key using any of these headers:
|
|
110
|
+
|
|
111
|
+
- `x-outline-api-key: your_api_key_here`
|
|
112
|
+
- `outline-api-key: your_api_key_here`
|
|
113
|
+
- `authorization: Bearer your_api_key_here`
|
|
114
|
+
|
|
115
|
+
If no header is provided, the server will fall back to the `OUTLINE_API_KEY` environment variable. If neither is available, the request will fail with an authentication error.
|
|
116
|
+
|
|
88
117
|
### Env vars
|
|
89
118
|
|
|
90
|
-
- `OUTLINE_API_KEY` (
|
|
119
|
+
- `OUTLINE_API_KEY` (_required for stdio, optional for HTTP/SSE_): your API key for outline
|
|
91
120
|
- `OUTLINE_API_URL` (_optional_): Alternative URL for your outline API (if using an alt domain/self-hosting)
|
|
92
121
|
- `OUTLINE_MCP_PORT` (_optional_): Specify the port on which the server will run (default: 6060)
|
|
93
122
|
- `OUTLINE_MCP_HOST` (_optional_): Host/IP to bind the server to (default: 127.0.0.1). Use 0.0.0.0 to bind to all network interfaces
|
package/build/index.js
CHANGED
|
@@ -3,29 +3,70 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/
|
|
|
3
3
|
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
4
4
|
import fastify from 'fastify';
|
|
5
5
|
import { getMcpServer } from './utils/getMcpServer.js';
|
|
6
|
-
|
|
6
|
+
import { RequestContext } from './utils/toolRegistry.js';
|
|
7
|
+
/**
|
|
8
|
+
* Extracts API key from request headers
|
|
9
|
+
*/
|
|
10
|
+
function extractApiKey(request) {
|
|
11
|
+
// Check common header variations
|
|
12
|
+
const headers = request.headers;
|
|
13
|
+
return (headers['x-outline-api-key'] ||
|
|
14
|
+
headers['outline-api-key'] ||
|
|
15
|
+
headers['authorization']?.replace(/^Bearer\s+/i, ''));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Sets up request context with API key
|
|
19
|
+
*/
|
|
20
|
+
function setupRequestContext(request) {
|
|
21
|
+
const apiKey = extractApiKey(request);
|
|
22
|
+
const envApiKey = process.env.OUTLINE_API_KEY;
|
|
23
|
+
if (apiKey) {
|
|
24
|
+
// Use header API key
|
|
25
|
+
const context = RequestContext.getInstance();
|
|
26
|
+
context.setApiKey(apiKey);
|
|
27
|
+
console.log('Using API key from request headers');
|
|
28
|
+
}
|
|
29
|
+
else if (envApiKey) {
|
|
30
|
+
// Use environment variable API key
|
|
31
|
+
const context = RequestContext.getInstance();
|
|
32
|
+
context.setApiKey(envApiKey);
|
|
33
|
+
console.log('Using API key from environment variable');
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// No API key available
|
|
37
|
+
console.log('No API key provided in headers and no default environment variable set.');
|
|
38
|
+
console.log('Please set the OUTLINE_API_KEY environment variable or provide it in the request headers.');
|
|
39
|
+
throw new Error('API key required: Set OUTLINE_API_KEY environment variable or provide x-outline-api-key header');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
7
42
|
// HTTP mode - default behavior
|
|
8
43
|
const app = fastify();
|
|
9
44
|
// Stateless mode (default, recommended for most deployments)
|
|
10
45
|
app.post('/mcp', async (request, reply) => {
|
|
11
46
|
try {
|
|
47
|
+
// Setup request context with API key
|
|
48
|
+
setupRequestContext(request);
|
|
49
|
+
const mcpServer = await getMcpServer();
|
|
12
50
|
const httpTransport = new StreamableHTTPServerTransport({
|
|
13
51
|
sessionIdGenerator: undefined,
|
|
14
52
|
});
|
|
15
53
|
reply.raw.on('close', () => {
|
|
16
54
|
httpTransport.close();
|
|
17
55
|
mcpServer.close();
|
|
56
|
+
// Clean up context
|
|
57
|
+
RequestContext.resetInstance();
|
|
18
58
|
});
|
|
19
59
|
await mcpServer.connect(httpTransport);
|
|
20
60
|
await httpTransport.handleRequest(request.raw, reply.raw, request.body);
|
|
21
61
|
}
|
|
22
62
|
catch (error) {
|
|
63
|
+
console.error('Error in /mcp endpoint:', error.message);
|
|
23
64
|
if (!reply.sent) {
|
|
24
65
|
reply.code(500).send({
|
|
25
66
|
jsonrpc: '2.0',
|
|
26
67
|
error: {
|
|
27
68
|
code: -32603,
|
|
28
|
-
message: 'Internal server error',
|
|
69
|
+
message: error.message || 'Internal server error',
|
|
29
70
|
},
|
|
30
71
|
id: null,
|
|
31
72
|
});
|
|
@@ -56,6 +97,9 @@ app.delete('/mcp', async (request, reply) => {
|
|
|
56
97
|
let sseTransport = null;
|
|
57
98
|
app.get('/sse', async (request, reply) => {
|
|
58
99
|
try {
|
|
100
|
+
// Setup request context with API key
|
|
101
|
+
setupRequestContext(request);
|
|
102
|
+
const mcpServer = await getMcpServer();
|
|
59
103
|
// Create SSE transport for legacy clients
|
|
60
104
|
if (!sseTransport) {
|
|
61
105
|
sseTransport = new SSEServerTransport('/messages', reply.raw);
|
|
@@ -63,13 +107,13 @@ app.get('/sse', async (request, reply) => {
|
|
|
63
107
|
}
|
|
64
108
|
}
|
|
65
109
|
catch (error) {
|
|
66
|
-
console.error(error);
|
|
110
|
+
console.error('Error in /sse endpoint:', error.message);
|
|
67
111
|
if (!reply.sent) {
|
|
68
112
|
reply.code(500).send({
|
|
69
113
|
jsonrpc: '2.0',
|
|
70
114
|
error: {
|
|
71
115
|
code: -32603,
|
|
72
|
-
message: 'Internal server error',
|
|
116
|
+
message: error.message || 'Internal server error',
|
|
73
117
|
},
|
|
74
118
|
id: null,
|
|
75
119
|
});
|
|
@@ -78,11 +122,18 @@ app.get('/sse', async (request, reply) => {
|
|
|
78
122
|
});
|
|
79
123
|
// Legacy message endpoint for older clients
|
|
80
124
|
app.post('/messages', async (req, res) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
125
|
+
try {
|
|
126
|
+
setupRequestContext(req);
|
|
127
|
+
if (!sseTransport) {
|
|
128
|
+
res.status(400).send('No transport found');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
await sseTransport.handlePostMessage(req.raw, res.raw, req.body);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.error('Error in /messages endpoint:', error.message);
|
|
135
|
+
res.status(500).send(error.message || 'Internal server error');
|
|
84
136
|
}
|
|
85
|
-
await sseTransport.handlePostMessage(req.raw, res.raw, req.body);
|
|
86
137
|
});
|
|
87
138
|
const PORT = process.env.OUTLINE_MCP_PORT ? parseInt(process.env.OUTLINE_MCP_PORT, 10) : 6060;
|
|
88
139
|
const HOST = process.env.OUTLINE_MCP_HOST || '127.0.0.1';
|
|
@@ -91,6 +142,10 @@ app.listen({ port: PORT, host: HOST }, (err, address) => {
|
|
|
91
142
|
console.error(err);
|
|
92
143
|
process.exit(1);
|
|
93
144
|
}
|
|
94
|
-
console.log(`\n\nOutline MCP Server running:\n\tstreamable-http:
|
|
95
|
-
console.log('
|
|
145
|
+
console.log(`\n\nOutline MCP Server running:\n\tstreamable-http: http://${HOST}:${PORT}/mcp\n\tsse (deprecated): http://${HOST}:${PORT}/sse\n\n`);
|
|
146
|
+
console.log('API Key Configuration:');
|
|
147
|
+
console.log('- Set OUTLINE_API_KEY environment variable for default authentication');
|
|
148
|
+
console.log('- Or provide x-outline-api-key header in requests for per-request authentication');
|
|
149
|
+
console.log('- Or provide authorization header with Bearer token');
|
|
150
|
+
console.log('\nTo use this MCP server in stdio mode, run it via `outline-mcp-server-stdio`.');
|
|
96
151
|
});
|
|
@@ -2,19 +2,56 @@ import axios from 'axios';
|
|
|
2
2
|
import { config } from 'dotenv';
|
|
3
3
|
import { dirname, join } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
+
import { RequestContext } from '../utils/toolRegistry.js';
|
|
5
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
7
|
config({ path: join(__dirname, '..', '.env') });
|
|
7
|
-
const API_KEY = process.env.OUTLINE_API_KEY;
|
|
8
8
|
const API_URL = process.env.OUTLINE_API_URL || 'https://app.getoutline.com/api';
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Creates an Outline API client with the specified API key
|
|
11
|
+
*/
|
|
12
|
+
export function createOutlineClient(apiKey) {
|
|
13
|
+
const key = apiKey || process.env.OUTLINE_API_KEY;
|
|
14
|
+
if (!key) {
|
|
15
|
+
throw new Error('OUTLINE_API_KEY must be provided either as parameter or environment variable');
|
|
16
|
+
}
|
|
17
|
+
return axios.create({
|
|
18
|
+
baseURL: API_URL,
|
|
19
|
+
headers: {
|
|
20
|
+
Authorization: `Bearer ${key}`,
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
Accept: 'application/json',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
11
25
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Gets an outline client using context API key first, then environment variable
|
|
28
|
+
*/
|
|
29
|
+
export function getOutlineClient() {
|
|
30
|
+
const context = RequestContext.getInstance();
|
|
31
|
+
const contextApiKey = context.getApiKey();
|
|
32
|
+
if (contextApiKey) {
|
|
33
|
+
return createOutlineClient(contextApiKey);
|
|
34
|
+
}
|
|
35
|
+
return createOutlineClient();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Gets the default outline client using environment variable
|
|
39
|
+
* Only validates when called, not on import
|
|
40
|
+
*/
|
|
41
|
+
export function getDefaultOutlineClient() {
|
|
42
|
+
return createOutlineClient();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Default client instance for backward compatibility
|
|
46
|
+
* Note: This will only validate API key when first accessed, not on import
|
|
47
|
+
*/
|
|
48
|
+
let _defaultClient = null;
|
|
49
|
+
export const outlineClient = new Proxy({}, {
|
|
50
|
+
get(target, prop) {
|
|
51
|
+
if (!_defaultClient) {
|
|
52
|
+
_defaultClient = getDefaultOutlineClient();
|
|
53
|
+
}
|
|
54
|
+
const value = _defaultClient[prop];
|
|
55
|
+
return typeof value === 'function' ? value.bind(_defaultClient) : value;
|
|
19
56
|
},
|
|
20
57
|
});
|
package/build/stdio.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { getMcpServer } from './utils/getMcpServer.js';
|
|
4
|
+
// Validate API key for stdio mode
|
|
5
|
+
if (!process.env.OUTLINE_API_KEY) {
|
|
6
|
+
console.error('Error: OUTLINE_API_KEY environment variable is required for stdio mode');
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
4
9
|
const mcpServer = await getMcpServer();
|
|
5
10
|
// STDIO mode - for direct client connections
|
|
6
11
|
const transport = new StdioServerTransport();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -11,7 +11,8 @@ toolRegistry.register('archive-document', {
|
|
|
11
11
|
},
|
|
12
12
|
async callback(args) {
|
|
13
13
|
try {
|
|
14
|
-
const
|
|
14
|
+
const client = getOutlineClient();
|
|
15
|
+
const response = await client.post('/documents.archive', {
|
|
15
16
|
id: args.id,
|
|
16
17
|
});
|
|
17
18
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -43,7 +43,8 @@ toolRegistry.register('ask_documents', {
|
|
|
43
43
|
if (args.dateFilter) {
|
|
44
44
|
payload.dateFilter = args.dateFilter;
|
|
45
45
|
}
|
|
46
|
-
const
|
|
46
|
+
const client = getOutlineClient();
|
|
47
|
+
const response = await client.post('/documents.answerQuestion', payload);
|
|
47
48
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
48
49
|
}
|
|
49
50
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -33,7 +33,8 @@ toolRegistry.register('create_collection', {
|
|
|
33
33
|
if (args.private !== undefined) {
|
|
34
34
|
payload.private = args.private;
|
|
35
35
|
}
|
|
36
|
-
const
|
|
36
|
+
const client = getOutlineClient();
|
|
37
|
+
const response = await client.post('/collections.create', payload);
|
|
37
38
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
38
39
|
}
|
|
39
40
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -27,7 +27,8 @@ toolRegistry.register('create_comment', {
|
|
|
27
27
|
if (args.data) {
|
|
28
28
|
payload.data = args.data;
|
|
29
29
|
}
|
|
30
|
-
const
|
|
30
|
+
const client = getOutlineClient();
|
|
31
|
+
const response = await client.post('/comments.create', payload);
|
|
31
32
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
32
33
|
}
|
|
33
34
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -33,7 +33,8 @@ toolRegistry.register('create_document', {
|
|
|
33
33
|
if (args.template !== undefined) {
|
|
34
34
|
payload.template = args.template;
|
|
35
35
|
}
|
|
36
|
-
const
|
|
36
|
+
const client = getOutlineClient();
|
|
37
|
+
const response = await client.post('/documents.create', payload);
|
|
37
38
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
38
39
|
}
|
|
39
40
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -14,7 +14,8 @@ toolRegistry.register('create_template_from_document', {
|
|
|
14
14
|
const payload = {
|
|
15
15
|
id: args.id,
|
|
16
16
|
};
|
|
17
|
-
const
|
|
17
|
+
const client = getOutlineClient();
|
|
18
|
+
const response = await client.post('/documents.templatize', payload);
|
|
18
19
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
19
20
|
}
|
|
20
21
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -11,7 +11,8 @@ toolRegistry.register('delete_comment', {
|
|
|
11
11
|
},
|
|
12
12
|
async callback(args) {
|
|
13
13
|
try {
|
|
14
|
-
const
|
|
14
|
+
const client = getOutlineClient();
|
|
15
|
+
const response = await client.post('/comments.delete', {
|
|
15
16
|
id: args.id,
|
|
16
17
|
});
|
|
17
18
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.success) }] };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -11,7 +11,8 @@ toolRegistry.register('delete_document', {
|
|
|
11
11
|
},
|
|
12
12
|
async callback(args) {
|
|
13
13
|
try {
|
|
14
|
-
const
|
|
14
|
+
const client = getOutlineClient();
|
|
15
|
+
const response = await client.post('/documents.delete', {
|
|
15
16
|
id: args.id,
|
|
16
17
|
});
|
|
17
18
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.success) }] };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -11,7 +11,8 @@ toolRegistry.register('get_collection', {
|
|
|
11
11
|
},
|
|
12
12
|
async callback(args) {
|
|
13
13
|
try {
|
|
14
|
-
const
|
|
14
|
+
const client = getOutlineClient();
|
|
15
|
+
const response = await client.post(`/collections.info`, { id: args.id });
|
|
15
16
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
16
17
|
}
|
|
17
18
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -13,7 +13,8 @@ toolRegistry.register('get_document', {
|
|
|
13
13
|
},
|
|
14
14
|
async callback(args) {
|
|
15
15
|
try {
|
|
16
|
-
const
|
|
16
|
+
const client = getOutlineClient();
|
|
17
|
+
const response = await client.post('/documents.info', { id: args.id });
|
|
17
18
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
18
19
|
}
|
|
19
20
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -15,7 +15,8 @@ toolRegistry.register('list_collections', {
|
|
|
15
15
|
if (args.limit) {
|
|
16
16
|
payload.limit = args.limit;
|
|
17
17
|
}
|
|
18
|
-
const
|
|
18
|
+
const client = getOutlineClient();
|
|
19
|
+
const response = await client.post('/collections.list', payload);
|
|
19
20
|
return {
|
|
20
21
|
content: [
|
|
21
22
|
{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -49,7 +49,8 @@ toolRegistry.register('list_documents', {
|
|
|
49
49
|
payload.query = args.query;
|
|
50
50
|
}
|
|
51
51
|
// Make the POST request to the documents.list endpoint
|
|
52
|
-
const
|
|
52
|
+
const client = getOutlineClient();
|
|
53
|
+
const response = await client.post('/documents.list', payload);
|
|
53
54
|
// Transform the response to a more usable format
|
|
54
55
|
const documents = response.data.data;
|
|
55
56
|
// Return the documents with additional metadata
|
package/build/tools/listUsers.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -55,7 +55,8 @@ toolRegistry.register('list_users', {
|
|
|
55
55
|
if (args.role) {
|
|
56
56
|
payload.role = args.role;
|
|
57
57
|
}
|
|
58
|
-
const
|
|
58
|
+
const client = getOutlineClient();
|
|
59
|
+
const response = await client.post('/users.list', payload);
|
|
59
60
|
return {
|
|
60
61
|
content: [
|
|
61
62
|
{ type: 'text', text: `users: ${JSON.stringify(response.data.data)}` },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -28,7 +28,8 @@ toolRegistry.register('move_document', {
|
|
|
28
28
|
if (args.parentDocumentId) {
|
|
29
29
|
payload.parentDocumentId = args.parentDocumentId;
|
|
30
30
|
}
|
|
31
|
-
const
|
|
31
|
+
const client = getOutlineClient();
|
|
32
|
+
const response = await client.post('/documents.move', payload);
|
|
32
33
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
33
34
|
}
|
|
34
35
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -22,7 +22,8 @@ toolRegistry.register('search_documents', {
|
|
|
22
22
|
if (args.limit) {
|
|
23
23
|
payload.limit = args.limit;
|
|
24
24
|
}
|
|
25
|
-
const
|
|
25
|
+
const client = getOutlineClient();
|
|
26
|
+
const response = await client.post('/documents.search', payload);
|
|
26
27
|
return {
|
|
27
28
|
content: [
|
|
28
29
|
{ type: 'text', text: `documents: ${JSON.stringify(response.data.data)}` },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -33,7 +33,8 @@ toolRegistry.register('update_collection', {
|
|
|
33
33
|
if (args.color) {
|
|
34
34
|
payload.color = args.color;
|
|
35
35
|
}
|
|
36
|
-
const
|
|
36
|
+
const client = getOutlineClient();
|
|
37
|
+
const response = await client.post('/collections.update', payload);
|
|
37
38
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
38
39
|
}
|
|
39
40
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -22,7 +22,8 @@ toolRegistry.register('update_comment', {
|
|
|
22
22
|
if (args.data) {
|
|
23
23
|
payload.data = args.data;
|
|
24
24
|
}
|
|
25
|
-
const
|
|
25
|
+
const client = getOutlineClient();
|
|
26
|
+
const response = await client.post('/comments.update', payload);
|
|
26
27
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
27
28
|
}
|
|
28
29
|
catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getOutlineClient } from '../outline/outlineClient.js';
|
|
3
3
|
import toolRegistry from '../utils/toolRegistry.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
// Register this tool
|
|
@@ -30,7 +30,8 @@ toolRegistry.register('update_document', {
|
|
|
30
30
|
if (args.done !== undefined) {
|
|
31
31
|
payload.done = args.done;
|
|
32
32
|
}
|
|
33
|
-
const
|
|
33
|
+
const client = getOutlineClient();
|
|
34
|
+
const response = await client.post('/documents.update', payload);
|
|
34
35
|
return { content: [{ type: 'text', text: JSON.stringify(response.data.data) }] };
|
|
35
36
|
}
|
|
36
37
|
catch (error) {
|
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
// Context to store request-specific data
|
|
2
|
+
export class RequestContext {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.context = new Map();
|
|
5
|
+
}
|
|
6
|
+
static getInstance() {
|
|
7
|
+
if (!RequestContext.instance) {
|
|
8
|
+
RequestContext.instance = new RequestContext();
|
|
9
|
+
}
|
|
10
|
+
return RequestContext.instance;
|
|
11
|
+
}
|
|
12
|
+
static resetInstance() {
|
|
13
|
+
RequestContext.instance = null;
|
|
14
|
+
}
|
|
15
|
+
set(key, value) {
|
|
16
|
+
this.context.set(key, value);
|
|
17
|
+
}
|
|
18
|
+
get(key) {
|
|
19
|
+
return this.context.get(key);
|
|
20
|
+
}
|
|
21
|
+
clear() {
|
|
22
|
+
this.context.clear();
|
|
23
|
+
}
|
|
24
|
+
getApiKey() {
|
|
25
|
+
return this.get('apiKey');
|
|
26
|
+
}
|
|
27
|
+
setApiKey(apiKey) {
|
|
28
|
+
this.set('apiKey', apiKey);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
RequestContext.instance = null;
|
|
1
32
|
class ToolRegistry {
|
|
2
33
|
constructor() {
|
|
3
34
|
this.registry = new Map();
|