mcp-outline 0.1.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Vortiago
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,170 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-outline
3
+ Version: 0.1.0
4
+ Summary: A Model Context Protocol (MCP) server for Outline (https://www.getoutline.com)
5
+ Author-email: "Atle H. Havsø" <atle@havso.net>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Vortiago
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/Vortiago/mcp-outline
29
+ Project-URL: Bug Tracker, https://github.com/Vortiago/mcp-outline/issues
30
+ Requires-Python: >=3.10
31
+ Description-Content-Type: text/markdown
32
+ License-File: LICENSE
33
+ Requires-Dist: mcp>=0.1.0
34
+ Requires-Dist: requests>=2.25.0
35
+ Provides-Extra: dev
36
+ Requires-Dist: mcp[cli]>=0.1.0; extra == "dev"
37
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
38
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
39
+ Requires-Dist: ruff>=0.0.267; extra == "dev"
40
+ Requires-Dist: anyio>=3.6.2; extra == "dev"
41
+ Requires-Dist: pyright>=1.1.350; extra == "dev"
42
+ Requires-Dist: trio>=0.22.0; extra == "dev"
43
+ Dynamic: license-file
44
+
45
+ # MCP Outline Server
46
+
47
+ A Model Context Protocol (MCP) server enabling AI assistants to interact with Outline (https://www.getoutline.com)
48
+
49
+ ## Overview
50
+
51
+ This project implements a Model Context Protocol (MCP) server that allows AI assistants (like Claude) to interact with Outline document services, providing a bridge between natural language interactions and Outline's document management capabilities.
52
+
53
+ ## Features
54
+
55
+ Currently implemented:
56
+ - **Document Search**: Search for documents by keywords
57
+ - **Collection Management**: List collections and view document structure
58
+ - **Document Reading**: Read document content, export as markdown
59
+ - **Comment Management**: View and add comments on documents
60
+ - **Document Creation**: Create new documents in collections
61
+ - **Document Editing**: Update document content and move documents
62
+ - **Backlink Management**: View documents that link to a specific document
63
+
64
+ ## Getting Started
65
+
66
+ ### Prerequisites
67
+
68
+ - Python 3.10+
69
+ - Outline account with API access
70
+ - Outline API key (get this from your Outline account settings)
71
+
72
+ ### Installation
73
+
74
+ ```bash
75
+ # Clone the repository
76
+ git clone https://github.com/Vortiago/mcp-outline.git
77
+ cd mcp-outline
78
+
79
+ # Install in development mode
80
+ uv pip install -e ".[dev]"
81
+ ```
82
+
83
+ ### Configuration
84
+
85
+ Create a `.env` file in the project root with the following variables:
86
+
87
+ ```
88
+ # Outline API Configuration
89
+ OUTLINE_API_KEY=your_outline_api_key_here
90
+
91
+ # For cloud-hosted Outline (default)
92
+ # OUTLINE_API_URL=https://app.getoutline.com/api
93
+
94
+ # For self-hosted Outline
95
+ # OUTLINE_API_URL=https://your-outline-instance.example.com/api
96
+ ```
97
+
98
+ ### Running the Server
99
+
100
+ ```bash
101
+ # Development mode with the MCP Inspector
102
+ mcp dev src/mcp_outline/server.py
103
+
104
+ # Or use the provided script
105
+ ./start_server.sh
106
+
107
+ # Install in Claude Desktop (if available)
108
+ mcp install src/mcp_outline/server.py --name "Document Outline Assistant"
109
+ ```
110
+
111
+ ## Usage Examples
112
+
113
+ ### Search for Documents
114
+
115
+ ```
116
+ Search for documents containing "project planning"
117
+ ```
118
+
119
+ ### List Collections
120
+
121
+ ```
122
+ Show me all available collections
123
+ ```
124
+
125
+ ### Read a Document
126
+
127
+ ```
128
+ Get the content of document with ID "docId123"
129
+ ```
130
+
131
+ ### Create a New Document
132
+
133
+ ```
134
+ Create a new document titled "Research Report" in collection "colId456" with content "# Introduction\n\nThis is a research report..."
135
+ ```
136
+
137
+ ### Add a Comment
138
+
139
+ ```
140
+ Add a comment to document "docId123" saying "This looks great, but we should add more details to the methodology section."
141
+ ```
142
+
143
+ ### Move a Document
144
+
145
+ ```
146
+ Move document "docId123" to collection "colId789"
147
+ ```
148
+
149
+ ## Contributing
150
+
151
+ Contributions are welcome! Please feel free to submit a Pull Request.
152
+
153
+ ## Development
154
+
155
+ ```bash
156
+ # Run tests
157
+ uv run pytest tests/
158
+
159
+ # Format code
160
+ uv run ruff format .
161
+ ```
162
+
163
+ ## License
164
+
165
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
166
+
167
+ ## Acknowledgments
168
+
169
+ - Built with [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
170
+ - Uses [Outline API](https://getoutline.com) for document management
@@ -0,0 +1,126 @@
1
+ # MCP Outline Server
2
+
3
+ A Model Context Protocol (MCP) server enabling AI assistants to interact with Outline (https://www.getoutline.com)
4
+
5
+ ## Overview
6
+
7
+ This project implements a Model Context Protocol (MCP) server that allows AI assistants (like Claude) to interact with Outline document services, providing a bridge between natural language interactions and Outline's document management capabilities.
8
+
9
+ ## Features
10
+
11
+ Currently implemented:
12
+ - **Document Search**: Search for documents by keywords
13
+ - **Collection Management**: List collections and view document structure
14
+ - **Document Reading**: Read document content, export as markdown
15
+ - **Comment Management**: View and add comments on documents
16
+ - **Document Creation**: Create new documents in collections
17
+ - **Document Editing**: Update document content and move documents
18
+ - **Backlink Management**: View documents that link to a specific document
19
+
20
+ ## Getting Started
21
+
22
+ ### Prerequisites
23
+
24
+ - Python 3.10+
25
+ - Outline account with API access
26
+ - Outline API key (get this from your Outline account settings)
27
+
28
+ ### Installation
29
+
30
+ ```bash
31
+ # Clone the repository
32
+ git clone https://github.com/Vortiago/mcp-outline.git
33
+ cd mcp-outline
34
+
35
+ # Install in development mode
36
+ uv pip install -e ".[dev]"
37
+ ```
38
+
39
+ ### Configuration
40
+
41
+ Create a `.env` file in the project root with the following variables:
42
+
43
+ ```
44
+ # Outline API Configuration
45
+ OUTLINE_API_KEY=your_outline_api_key_here
46
+
47
+ # For cloud-hosted Outline (default)
48
+ # OUTLINE_API_URL=https://app.getoutline.com/api
49
+
50
+ # For self-hosted Outline
51
+ # OUTLINE_API_URL=https://your-outline-instance.example.com/api
52
+ ```
53
+
54
+ ### Running the Server
55
+
56
+ ```bash
57
+ # Development mode with the MCP Inspector
58
+ mcp dev src/mcp_outline/server.py
59
+
60
+ # Or use the provided script
61
+ ./start_server.sh
62
+
63
+ # Install in Claude Desktop (if available)
64
+ mcp install src/mcp_outline/server.py --name "Document Outline Assistant"
65
+ ```
66
+
67
+ ## Usage Examples
68
+
69
+ ### Search for Documents
70
+
71
+ ```
72
+ Search for documents containing "project planning"
73
+ ```
74
+
75
+ ### List Collections
76
+
77
+ ```
78
+ Show me all available collections
79
+ ```
80
+
81
+ ### Read a Document
82
+
83
+ ```
84
+ Get the content of document with ID "docId123"
85
+ ```
86
+
87
+ ### Create a New Document
88
+
89
+ ```
90
+ Create a new document titled "Research Report" in collection "colId456" with content "# Introduction\n\nThis is a research report..."
91
+ ```
92
+
93
+ ### Add a Comment
94
+
95
+ ```
96
+ Add a comment to document "docId123" saying "This looks great, but we should add more details to the methodology section."
97
+ ```
98
+
99
+ ### Move a Document
100
+
101
+ ```
102
+ Move document "docId123" to collection "colId789"
103
+ ```
104
+
105
+ ## Contributing
106
+
107
+ Contributions are welcome! Please feel free to submit a Pull Request.
108
+
109
+ ## Development
110
+
111
+ ```bash
112
+ # Run tests
113
+ uv run pytest tests/
114
+
115
+ # Format code
116
+ uv run ruff format .
117
+ ```
118
+
119
+ ## License
120
+
121
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
122
+
123
+ ## Acknowledgments
124
+
125
+ - Built with [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
126
+ - Uses [Outline API](https://getoutline.com) for document management
@@ -0,0 +1,58 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "mcp-outline"
7
+ description = "A Model Context Protocol (MCP) server for Outline (https://www.getoutline.com)"
8
+ version = "0.1.0"
9
+ authors = [
10
+ {name = "Atle H. Havsø", email = "atle@havso.net"},
11
+ ]
12
+ requires-python = ">=3.10"
13
+ readme = "README.md"
14
+ license = {file = "LICENSE"}
15
+ dependencies = [
16
+ "mcp>=0.1.0",
17
+ "requests>=2.25.0",
18
+ ]
19
+
20
+ [project.scripts]
21
+ mcp-outline = "mcp_outline.server:main"
22
+
23
+ [project.urls]
24
+ "Homepage" = "https://github.com/Vortiago/mcp-outline"
25
+ "Bug Tracker" = "https://github.com/Vortiago/mcp-outline/issues"
26
+
27
+ [project.optional-dependencies]
28
+ dev = [
29
+ "mcp[cli]>=0.1.0",
30
+ "pytest>=7.0.0",
31
+ "pytest-asyncio>=0.21.0",
32
+ "ruff>=0.0.267",
33
+ "anyio>=3.6.2",
34
+ "pyright>=1.1.350",
35
+ "trio>=0.22.0",
36
+ ]
37
+
38
+ [tool.setuptools]
39
+ package-dir = {"" = "src"}
40
+
41
+ [tool.pytest.ini_options]
42
+ testpaths = ["tests"]
43
+ python_files = "test_*.py"
44
+ python_functions = "test_*"
45
+
46
+ [tool.ruff]
47
+ line-length = 79
48
+ target-version = "py310"
49
+ select = ["E", "F", "I"]
50
+ extend-exclude = ["docs"]
51
+
52
+ [tool.pyright]
53
+ exclude = [
54
+ "**/node_modules",
55
+ "**/__pycache__",
56
+ "**/.*",
57
+ "docs/"
58
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,4 @@
1
+ # MCP Outline package
2
+ """
3
+ MCP server for document outlines
4
+ """
@@ -0,0 +1,7 @@
1
+ """
2
+ Main module for MCP Outline server
3
+ """
4
+ from mcp_outline.server import main
5
+
6
+ if __name__ == "__main__":
7
+ main()
@@ -0,0 +1,12 @@
1
+ # Document Outline MCP features package
2
+ from mcp_outline.features import documents
3
+
4
+
5
+ def register_all(mcp):
6
+ """
7
+ Register all features with the MCP server.
8
+
9
+ Args:
10
+ mcp: The FastMCP server instance
11
+ """
12
+ documents.register(mcp)
@@ -0,0 +1,18 @@
1
+ # Document management features for MCP Outline
2
+ from typing import Optional
3
+ from mcp_outline.features.documents import tools
4
+ from mcp_outline.features.documents import document_reading
5
+ from mcp_outline.features.documents import document_editing
6
+
7
+ def register(mcp, api_key: Optional[str] = None, api_url: Optional[str] = None):
8
+ """
9
+ Register document management features with the MCP server.
10
+
11
+ Args:
12
+ mcp: The FastMCP server instance
13
+ api_key: Optional API key for Outline
14
+ api_url: Optional API URL for Outline
15
+ """
16
+ tools.register_tools(mcp)
17
+ document_reading.register_tools(mcp)
18
+ document_editing.register_tools(mcp)
@@ -0,0 +1,39 @@
1
+ """
2
+ Common utilities for document outline features.
3
+
4
+ This module provides shared functionality used by both tools and resources.
5
+ """
6
+ import os
7
+ from mcp_outline.utils.outline_client import OutlineClient, OutlineError
8
+
9
+ class OutlineClientError(Exception):
10
+ """Exception raised for errors in document outline client operations."""
11
+ pass
12
+
13
+ def get_outline_client() -> OutlineClient:
14
+ """
15
+ Get the document outline client.
16
+
17
+ Returns:
18
+ OutlineClient instance
19
+
20
+ Raises:
21
+ OutlineClientError: If client creation fails
22
+ """
23
+ try:
24
+ # Get API credentials from environment variables
25
+ api_key = os.getenv("OUTLINE_API_KEY")
26
+ api_url = os.getenv("OUTLINE_API_URL")
27
+
28
+ # Create an instance of the outline client
29
+ client = OutlineClient(api_key=api_key, api_url=api_url)
30
+
31
+ # Test the connection by attempting to get auth info
32
+ auth_info = client.auth_info()
33
+ user_name = auth_info.get('user', {}).get('name', 'Unknown')
34
+
35
+ return client
36
+ except OutlineError as e:
37
+ raise OutlineClientError(f"Outline client error: {str(e)}")
38
+ except Exception as e:
39
+ raise OutlineClientError(f"Unexpected error: {str(e)}")
@@ -0,0 +1,191 @@
1
+ """
2
+ Document editing tools for the MCP Outline server.
3
+
4
+ This module provides MCP tools for creating and updating documents.
5
+ """
6
+ from typing import Optional, Dict, Any
7
+
8
+ from mcp_outline.features.documents.common import get_outline_client, OutlineClientError
9
+
10
+ def register_tools(mcp) -> None:
11
+ """
12
+ Register document editing tools with the MCP server.
13
+
14
+ Args:
15
+ mcp: The FastMCP server instance
16
+ """
17
+ @mcp.tool()
18
+ def create_document(
19
+ title: str,
20
+ collection_id: str,
21
+ text: str = "",
22
+ parent_document_id: Optional[str] = None,
23
+ publish: bool = True
24
+ ) -> str:
25
+ """
26
+ Create a new document.
27
+
28
+ Args:
29
+ title: The document title
30
+ collection_id: The collection ID to create the document in
31
+ text: Optional markdown content for the document
32
+ parent_document_id: Optional parent document ID for nesting
33
+ publish: Whether to publish the document immediately
34
+
35
+ Returns:
36
+ Result message with the new document ID
37
+ """
38
+ try:
39
+ client = get_outline_client()
40
+
41
+ data = {
42
+ "title": title,
43
+ "text": text,
44
+ "collectionId": collection_id,
45
+ "publish": publish
46
+ }
47
+
48
+ if parent_document_id:
49
+ data["parentDocumentId"] = parent_document_id
50
+
51
+ response = client.post("documents.create", data)
52
+ document = response.get("data", {})
53
+
54
+ if not document:
55
+ return "Failed to create document."
56
+
57
+ doc_id = document.get("id", "unknown")
58
+ doc_title = document.get("title", "Untitled")
59
+
60
+ return f"Document created successfully: {doc_title} (ID: {doc_id})"
61
+ except OutlineClientError as e:
62
+ return f"Error creating document: {str(e)}"
63
+ except Exception as e:
64
+ return f"Unexpected error: {str(e)}"
65
+
66
+ @mcp.tool()
67
+ def update_document(
68
+ document_id: str,
69
+ title: Optional[str] = None,
70
+ text: Optional[str] = None,
71
+ append: bool = False
72
+ ) -> str:
73
+ """
74
+ Update an existing document.
75
+
76
+ Args:
77
+ document_id: The document ID to update
78
+ title: New title (if None, keeps existing title)
79
+ text: New content (if None, keeps existing content)
80
+ append: If True, appends text instead of replacing
81
+
82
+ Returns:
83
+ Result message
84
+ """
85
+ try:
86
+ client = get_outline_client()
87
+
88
+ # Only include fields that are being updated
89
+ data: Dict[str, Any] = {"id": document_id}
90
+
91
+ if title is not None:
92
+ data["title"] = title
93
+
94
+ if text is not None:
95
+ data["text"] = text
96
+ data["append"] = append
97
+
98
+ response = client.post("documents.update", data)
99
+ document = response.get("data", {})
100
+
101
+ if not document:
102
+ return "Failed to update document."
103
+
104
+ doc_title = document.get("title", "Untitled")
105
+
106
+ return f"Document updated successfully: {doc_title}"
107
+ except OutlineClientError as e:
108
+ return f"Error updating document: {str(e)}"
109
+ except Exception as e:
110
+ return f"Unexpected error: {str(e)}"
111
+
112
+ @mcp.tool()
113
+ def move_document(
114
+ document_id: str,
115
+ collection_id: Optional[str] = None,
116
+ parent_document_id: Optional[str] = None
117
+ ) -> str:
118
+ """
119
+ Move a document to a different collection or parent.
120
+
121
+ Args:
122
+ document_id: The document ID to move
123
+ collection_id: Target collection ID
124
+ parent_document_id: Optional parent document ID
125
+
126
+ Returns:
127
+ Result message
128
+ """
129
+ try:
130
+ client = get_outline_client()
131
+
132
+ # Require at least one destination parameter
133
+ if collection_id is None and parent_document_id is None:
134
+ return "Error: You must specify either a collection_id or parent_document_id."
135
+
136
+ data = {"id": document_id}
137
+
138
+ if collection_id:
139
+ data["collectionId"] = collection_id
140
+
141
+ if parent_document_id:
142
+ data["parentDocumentId"] = parent_document_id
143
+
144
+ response = client.post("documents.move", data)
145
+
146
+ # Check for successful response
147
+ if response.get("data"):
148
+ return "Document moved successfully."
149
+ else:
150
+ return "Failed to move document."
151
+ except OutlineClientError as e:
152
+ return f"Error moving document: {str(e)}"
153
+ except Exception as e:
154
+ return f"Unexpected error: {str(e)}"
155
+
156
+ @mcp.tool()
157
+ def add_comment(
158
+ document_id: str,
159
+ text: str
160
+ ) -> str:
161
+ """
162
+ Add a comment to a document.
163
+
164
+ Args:
165
+ document_id: The document to comment on
166
+ text: The comment text (supports markdown)
167
+
168
+ Returns:
169
+ Result message with the new comment ID
170
+ """
171
+ try:
172
+ client = get_outline_client()
173
+
174
+ data = {
175
+ "documentId": document_id,
176
+ "text": text
177
+ }
178
+
179
+ response = client.post("comments.create", data)
180
+ comment = response.get("data", {})
181
+
182
+ if not comment:
183
+ return "Failed to create comment."
184
+
185
+ comment_id = comment.get("id", "unknown")
186
+
187
+ return f"Comment added successfully (ID: {comment_id})"
188
+ except OutlineClientError as e:
189
+ return f"Error adding comment: {str(e)}"
190
+ except Exception as e:
191
+ return f"Unexpected error: {str(e)}"