outline-mcp-server 4.12.3 → 5.0.1
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 +27 -16
- package/build/index.js +53 -51
- package/build/tools/archiveDocument.js +7 -13
- package/build/tools/askDocuments.js +21 -35
- package/build/tools/createCollection.js +14 -29
- package/build/tools/createComment.js +13 -25
- package/build/tools/createDocument.js +15 -34
- package/build/tools/createTemplateFromDocument.js +7 -13
- package/build/tools/deleteComment.js +7 -13
- package/build/tools/deleteDocument.js +7 -13
- package/build/tools/getCollection.js +7 -13
- package/build/tools/getDocument.js +9 -13
- package/build/tools/listCollections.js +18 -12
- package/build/tools/listDocuments.js +34 -55
- package/build/tools/listUsers.js +31 -46
- package/build/tools/moveDocument.js +15 -21
- package/build/tools/searchDocuments.js +14 -21
- package/build/tools/updateCollection.js +14 -29
- package/build/tools/updateComment.js +9 -21
- package/build/tools/updateDocument.js +11 -29
- package/build/utils/getMcpServer.js +16 -0
- package/build/utils/{importTools.js → loadAllTools.js} +8 -5
- package/build/utils/toolRegistry.js +27 -0
- package/package.json +18 -21
- package/bin/cli.js +0 -57
- package/build/e2e/archiveDocument.spec.js +0 -7
- package/build/e2e/askDocuments.spec.js +0 -7
- package/build/e2e/createCollection.spec.js +0 -7
- package/build/e2e/createComment.spec.js +0 -7
- package/build/e2e/createDocument.spec.js +0 -7
- package/build/e2e/createTemplateFromDocument.spec.js +0 -7
- package/build/e2e/deleteComment.spec.js +0 -7
- package/build/e2e/deleteDocument.spec.js +0 -7
- package/build/e2e/getCollection.spec.js +0 -7
- package/build/e2e/getDocument.spec.js +0 -7
- package/build/e2e/listCollections.spec.js +0 -7
- package/build/e2e/listDocuments.spec.js +0 -7
- package/build/e2e/moveDocument.spec.js +0 -7
- package/build/e2e/searchDocuments.spec.js +0 -7
- package/build/e2e/setup.js +0 -33
- package/build/e2e/updateCollection.spec.js +0 -7
- package/build/e2e/updateComment.spec.js +0 -7
- package/build/e2e/updateDocument.spec.js +0 -7
- package/build/e2e/util/smokeTest.js +0 -88
- package/build/types.js +0 -1
- package/build/utils/listTools.js +0 -10
- /package/build/{client.js → outline/outlineClient.js} +0 -0
package/package.json
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
{
|
2
2
|
"name": "outline-mcp-server",
|
3
|
-
"version": "
|
3
|
+
"version": "5.0.1",
|
4
4
|
"description": "An MCP server for interacting with Outline's API",
|
5
5
|
"type": "module",
|
6
6
|
"bin": {
|
7
|
-
"outline-mcp-server": "./
|
8
|
-
"outline-mcp-server-stdio": "./build/index.js"
|
7
|
+
"outline-mcp-server": "./build/index.js"
|
9
8
|
},
|
10
9
|
"files": [
|
11
10
|
"build",
|
@@ -20,34 +19,32 @@
|
|
20
19
|
"url": "https://github.com/mmmeff/outline-mcp-server"
|
21
20
|
},
|
22
21
|
"scripts": {
|
23
|
-
"build": "tsc && chmod +x build/index.js
|
22
|
+
"build": "tsc && chmod +x build/index.js",
|
24
23
|
"prepare": "npm run build",
|
25
|
-
"watch": "
|
26
|
-
"dev": "concurrently -n 'build,inspector' -c 'blue.bold,green.bold' 'npm run watch' '
|
27
|
-
"
|
28
|
-
"start": "
|
24
|
+
"watch": "bun --watch src/index.ts",
|
25
|
+
"dev": "concurrently -n 'build,inspector' -c 'blue.bold,green.bold' 'npm run watch' 'npm run inspector'",
|
26
|
+
"inspector": "npx @modelcontextprotocol/inspector@latest -y",
|
27
|
+
"start": "bun build/index.js",
|
29
28
|
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\"",
|
30
|
-
"semantic-release": "semantic-release"
|
31
|
-
"test:e2e": "playwright test",
|
32
|
-
"test:e2e:ui": "playwright test --ui",
|
33
|
-
"test:e2e:debug": "playwright test --debug"
|
29
|
+
"semantic-release": "semantic-release"
|
34
30
|
},
|
35
31
|
"dependencies": {
|
36
|
-
"@modelcontextprotocol/sdk": "
|
37
|
-
"axios": "
|
38
|
-
"
|
39
|
-
"
|
32
|
+
"@modelcontextprotocol/sdk": "1.12.1",
|
33
|
+
"axios": "1.9.0",
|
34
|
+
"bun": "^1.2.15",
|
35
|
+
"dotenv": "16.5.0",
|
36
|
+
"fastify": "^4.28.1",
|
37
|
+
"omit-ts": "^2.0.1",
|
38
|
+
"zod": "3.25.61"
|
40
39
|
},
|
41
40
|
"devDependencies": {
|
42
|
-
"@faker-js/faker": "^9.6.0",
|
43
|
-
"@playwright/test": "^1.42.1",
|
44
41
|
"@semantic-release/changelog": "^6.0.3",
|
45
42
|
"@semantic-release/git": "^10.0.1",
|
46
|
-
"@types/node": "
|
43
|
+
"@types/node": "20.x",
|
47
44
|
"concurrently": "^9.1.2",
|
48
45
|
"prettier": "^3.2.5",
|
49
46
|
"semantic-release": "^22.0.12",
|
50
|
-
"typescript": "
|
47
|
+
"typescript": "5.x"
|
51
48
|
},
|
52
49
|
"keywords": [
|
53
50
|
"outline",
|
@@ -57,6 +54,6 @@
|
|
57
54
|
],
|
58
55
|
"license": "MIT",
|
59
56
|
"engines": {
|
60
|
-
"node": ">=
|
57
|
+
"node": ">=20"
|
61
58
|
}
|
62
59
|
}
|
package/bin/cli.js
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
|
3
|
-
import { spawn } from 'child_process';
|
4
|
-
import { fileURLToPath } from 'url';
|
5
|
-
import { dirname, resolve } from 'path';
|
6
|
-
|
7
|
-
// Get the directory of the current script
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
9
|
-
const __dirname = dirname(__filename);
|
10
|
-
|
11
|
-
// Parse command line arguments
|
12
|
-
const args = process.argv.slice(2);
|
13
|
-
let port = 6060; // Default port
|
14
|
-
|
15
|
-
// Parse --port argument
|
16
|
-
for (let i = 0; i < args.length; i++) {
|
17
|
-
if (args[i] === '--port' && i + 1 < args.length) {
|
18
|
-
port = parseInt(args[i + 1], 10);
|
19
|
-
// Remove these arguments so they don't get passed to supergateway
|
20
|
-
args.splice(i, 2);
|
21
|
-
i--;
|
22
|
-
}
|
23
|
-
}
|
24
|
-
|
25
|
-
// Check for required environment variable
|
26
|
-
if (!process.env.OUTLINE_API_KEY) {
|
27
|
-
console.error('\x1b[31mError: OUTLINE_API_KEY environment variable is required but not set.\x1b[0m');
|
28
|
-
console.error('Please set this environment variable before running the server.');
|
29
|
-
process.exit(1);
|
30
|
-
}
|
31
|
-
|
32
|
-
// Path to the built index.js file
|
33
|
-
const serverPath = resolve(__dirname, '../build/index.js');
|
34
|
-
|
35
|
-
// Spawn the supergateway process
|
36
|
-
const gateway = spawn('npx', [
|
37
|
-
'-y',
|
38
|
-
'supergateway',
|
39
|
-
'--port',
|
40
|
-
port.toString(),
|
41
|
-
'--stdio',
|
42
|
-
`node ${serverPath}`
|
43
|
-
], {
|
44
|
-
stdio: 'inherit',
|
45
|
-
shell: true
|
46
|
-
});
|
47
|
-
|
48
|
-
// Handle process exit
|
49
|
-
process.on('SIGINT', () => {
|
50
|
-
console.log('SIGINT received, killing outline-mcp-server');
|
51
|
-
gateway.kill('SIGINT');
|
52
|
-
});
|
53
|
-
|
54
|
-
gateway.on('close', (code) => {
|
55
|
-
console.log('outline-mcp-server exited with code', code);
|
56
|
-
process.exit(code);
|
57
|
-
});
|
@@ -1,7 +0,0 @@
|
|
1
|
-
import test from '@playwright/test';
|
2
|
-
import runSmokeTestForTool from './util/smokeTest';
|
3
|
-
test.describe('create_template_from_document', () => {
|
4
|
-
test('passes a smoke test', async ({ page }) => {
|
5
|
-
await runSmokeTestForTool(page, 'create_template_from_document');
|
6
|
-
});
|
7
|
-
});
|
package/build/e2e/setup.js
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
import { test } from '@playwright/test';
|
2
|
-
import { registerTools } from '../utils/importTools.js';
|
3
|
-
/**
|
4
|
-
* Helper function to mock API responses
|
5
|
-
*/
|
6
|
-
export async function mockApiResponse(page, url, response) {
|
7
|
-
await page.route(url, route => {
|
8
|
-
route.fulfill({
|
9
|
-
status: 200,
|
10
|
-
contentType: 'application/json',
|
11
|
-
body: JSON.stringify(response),
|
12
|
-
});
|
13
|
-
});
|
14
|
-
}
|
15
|
-
/**
|
16
|
-
* Helper function to wait for API calls
|
17
|
-
*/
|
18
|
-
export async function loadTool(page, toolName) {
|
19
|
-
return await test.step(`Loading tool: ${toolName}`, async () => {
|
20
|
-
const toolDefinitions = await registerTools();
|
21
|
-
const tool = toolDefinitions[toolName];
|
22
|
-
if (!tool) {
|
23
|
-
// TODO: Make this actually type-safe instead of a runtime error
|
24
|
-
throw new Error(`Tool not found for name: ${toolName}`);
|
25
|
-
}
|
26
|
-
await page.goto('/');
|
27
|
-
await page.getByRole('button', { name: 'Connect' }).click();
|
28
|
-
await page.getByRole('button', { name: 'List Tools' }).click();
|
29
|
-
await page.getByText(toolName).click();
|
30
|
-
await page.waitForTimeout(100);
|
31
|
-
return tool;
|
32
|
-
});
|
33
|
-
}
|
@@ -1,88 +0,0 @@
|
|
1
|
-
import { faker } from '@faker-js/faker';
|
2
|
-
import test from '@playwright/test';
|
3
|
-
import { loadTool } from '../setup.js';
|
4
|
-
export default async function runSmokeTestForTool(page, toolName) {
|
5
|
-
const tool = await loadTool(page, toolName);
|
6
|
-
await test.step('Fill in required fields', async () => {
|
7
|
-
const requiredProperties = tool.inputSchema.required ?? [];
|
8
|
-
console.log('requiredProperties', requiredProperties);
|
9
|
-
for (let property of Object.entries(tool.inputSchema.properties ?? {}).filter(([name]) => requiredProperties.includes(name))) {
|
10
|
-
const [name, config] = property;
|
11
|
-
const input = page.getByPlaceholder(config.description);
|
12
|
-
switch (config.type) {
|
13
|
-
case 'string':
|
14
|
-
if (config.enum) {
|
15
|
-
// If it's an enum, select a random value from the enum array
|
16
|
-
await input.fill(faker.helpers.arrayElement(config.enum));
|
17
|
-
}
|
18
|
-
else if (name.toLowerCase().includes('id')) {
|
19
|
-
// Generate a realistic-looking ID
|
20
|
-
await input.fill(faker.string.alphanumeric(10));
|
21
|
-
}
|
22
|
-
else if (name.toLowerCase().includes('email')) {
|
23
|
-
// Generate email if the field name suggests it's an email
|
24
|
-
await input.fill(faker.internet.email());
|
25
|
-
}
|
26
|
-
else if (name.toLowerCase().includes('date') || name.toLowerCase().includes('time')) {
|
27
|
-
// Generate date string if the field name suggests it's a date
|
28
|
-
await input.fill(faker.date.recent().toISOString());
|
29
|
-
}
|
30
|
-
else if (name.toLowerCase().includes('color')) {
|
31
|
-
// Generate color hex code
|
32
|
-
await input.fill(faker.color.rgb({ format: 'hex' }));
|
33
|
-
}
|
34
|
-
else if (name.toLowerCase().includes('url') || name.toLowerCase().includes('link')) {
|
35
|
-
// Generate URL
|
36
|
-
await input.fill(faker.internet.url());
|
37
|
-
}
|
38
|
-
else {
|
39
|
-
// For general string fields
|
40
|
-
await input.fill(faker.lorem.sentence());
|
41
|
-
}
|
42
|
-
break;
|
43
|
-
case 'number':
|
44
|
-
await input.fill(faker.number.int({ min: 1, max: 100 }).toString());
|
45
|
-
break;
|
46
|
-
case 'boolean':
|
47
|
-
// For boolean inputs, let's use random true/false
|
48
|
-
await input.fill(faker.datatype.boolean().toString());
|
49
|
-
break;
|
50
|
-
case 'array':
|
51
|
-
// For array inputs, we'll generate a JSON string with a few items
|
52
|
-
const arrayItems = [];
|
53
|
-
// Look at array item type and generate appropriate fake data
|
54
|
-
if (config.items?.type === 'string') {
|
55
|
-
for (let i = 0; i < 3; i++) {
|
56
|
-
arrayItems.push(faker.lorem.word());
|
57
|
-
}
|
58
|
-
}
|
59
|
-
else if (config.items?.type === 'number') {
|
60
|
-
for (let i = 0; i < 3; i++) {
|
61
|
-
arrayItems.push(faker.number.int(100));
|
62
|
-
}
|
63
|
-
}
|
64
|
-
await input.fill(JSON.stringify(arrayItems));
|
65
|
-
break;
|
66
|
-
case 'object':
|
67
|
-
// For object inputs, generate a simple object with some properties
|
68
|
-
const fakeObject = {
|
69
|
-
prop1: faker.lorem.word(),
|
70
|
-
prop2: faker.number.int(100),
|
71
|
-
prop3: faker.datatype.boolean(),
|
72
|
-
};
|
73
|
-
await input.fill(JSON.stringify(fakeObject));
|
74
|
-
break;
|
75
|
-
default:
|
76
|
-
// For unhandled types, generate a basic string
|
77
|
-
await input.fill(faker.lorem.word());
|
78
|
-
break;
|
79
|
-
}
|
80
|
-
}
|
81
|
-
});
|
82
|
-
await test.step('Execute the tool', async () => {
|
83
|
-
await page.getByRole('button', { name: 'Run Tool' }).click();
|
84
|
-
await page.getByRole('heading', { name: 'Tool Result: Success' }).isVisible();
|
85
|
-
await page.getByRole('heading', { name: 'Error output from MCP server' }).isHidden();
|
86
|
-
await page.waitForTimeout(100);
|
87
|
-
});
|
88
|
-
}
|
package/build/types.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|
package/build/utils/listTools.js
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
// We'll collect all tool definitions here, keyed by name
|
2
|
-
const toolDefinitions = {};
|
3
|
-
// Function to register a tool definition
|
4
|
-
export function registerTool(definition) {
|
5
|
-
toolDefinitions[definition.name] = definition;
|
6
|
-
}
|
7
|
-
// Function to get all registered tool definitions
|
8
|
-
export function getToolDefinitions() {
|
9
|
-
return toolDefinitions;
|
10
|
-
}
|
File without changes
|