login works, but not search

This commit is contained in:
Isaac Johnson 2025-10-06 19:10:22 -05:00
commit 62cd8dea26
5 changed files with 243 additions and 0 deletions

18
Dockerfile Normal file
View File

@ -0,0 +1,18 @@
FROM python:3.13-slim
ARG VIKUNJA_URL
ARG VIKUNJA_USERNAME
ARG VIKUNJA_PASSWORD
ENV VIKUNJA_URL=$VIKUNJA_URL
ENV VIKUNJA_USERNAME=$VIKUNJA_USERNAME
ENV VIKUNJA_PASSWORD=$VIKUNJA_PASSWORD
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]

89
INSTALL.md Normal file
View File

@ -0,0 +1,89 @@
# Installation Guide for Vikunja MCP Server
This guide provides instructions for setting up and running the Vikunja MCP server locally.
## Prerequisites
- Python 3.10 or newer
- `pip` (Python's package installer)
## Setup Instructions
Follow these steps to get the application running.
**1. Create a Virtual Environment**
It is highly recommended to run this application in a Python virtual environment to avoid conflicts with system-wide packages.
Create the environment using the following command:
```bash
python3 -m venv .venv
```
**2. Activate the Virtual Environment**
Before installing dependencies or running the application, you must activate the virtual environment.
* **On macOS and Linux:**
```bash
source .venv/bin/activate
```
* **On Windows:**
```bash
.\.venv\Scripts\activate
```
Your terminal prompt should change to indicate that you are now in the `.venv` environment.
**3. Install Dependencies**
With the virtual environment active, install the required Python packages from the `requirements.txt` file.
```bash
pip install -r requirements.txt
```
## Configuration
The application requires three environment variables to connect to your Vikunja instance. You must set these in your terminal before running the server.
Replace the placeholder values with your actual credentials.
```bash
export VIKUNJA_URL="https://your-vikunja-instance.com"
export VIKUNJA_USERNAME="your_username"
export VIKUNJA_PASSWORD="your_password"
```
**Note:** These variables are only set for the current terminal session. If you open a new terminal, you will need to set them again.
## Running the Application
Once the setup and configuration are complete, you can run the application with the following command:
```bash
python main.py
```
This will launch the interactive MCP shell.
## Usage
Here are the basic commands to get started:
1. **Log in** to your Vikunja instance:
```
> login
```
2. **Search for tasks**:
```
> search_tasks "My search query"
```
3. **Add a new task** to a project:
```
> add_task <project_id> "My new task title"
```
You can type `help` at any time to see a full list of commands, or `help <command_name>` for details on a specific one. To close the application, type `exit`.

45
USAGE.md Normal file
View File

@ -0,0 +1,45 @@
# Usage
This document provides instructions on how to add and use the Vikunja MCP server with the Gemini CLI.
## Prerequisites
Before adding the MCP server, you need to set the following environment variables:
```bash
export VIKUNJA_URL="<your_vikunja_url>"
export VIKUNJA_USERNAME="<your_vikunja_username>"
export VIKUNJA_PASSWORD="<your_vikunja_password>"
```
## Adding the MCP Server
To add the Vikunja MCP server to the Gemini CLI, use the following command:
```bash
gemini mcp add --name vikunja --command "python main.py"
```
## Starting the MCP Server
To start the Vikunja MCP server, use the following command:
```bash
gemini mcp start vikunja
```
## Stopping the MCP Server
To stop the Vikunja MCP server, use the following command:
```bash
gemini mcp stop vikunja
```
## Removing the MCP Server
To remove the Vikunja MCP server from the Gemini CLI, use the following command:
```bash
gemini mcp remove vikunja
```

89
main.py Normal file
View File

@ -0,0 +1,89 @@
import os
import requests
from fastmcp import FastMCP
# --- Configuration ---
VIKUNJA_URL = os.getenv("VIKUNJA_URL")
VIKUNJA_USERNAME = os.getenv("VIKUNJA_USERNAME")
VIKUNJA_PASSWORD = os.getenv("VIKUNJA_PASSWORD")
# --- MCP Application Setup ---
mcp = FastMCP()
session = requests.Session()
# --- Input Validation ---
if not all([VIKUNJA_URL, VIKUNJA_USERNAME, VIKUNJA_PASSWORD]):
print("Error: Please set the VIKUNJA_URL, VIKUNJA_USERNAME, and VIKUNJA_PASSWORD environment variables.")
exit(1)
@mcp.tool()
def login():
"""
Authenticates with the Vikunja API to get a session token.
"""
global session
try:
response = session.post(
f"{VIKUNJA_URL}/api/v1/login",
json={"username": VIKUNJA_USERNAME, "password": VIKUNJA_PASSWORD}
)
response.raise_for_status()
token = response.json().get("token")
if not token:
return "Login failed: Token not found in response."
session.headers.update({"Authorization": f"Bearer {token}"})
return "Login successful. Token stored for session."
except requests.exceptions.RequestException as e:
return f"Login failed: {e}"
@mcp.tool()
def search_tasks(query: str):
"""
Searches for tasks in Vikunja.
:param query: The search string to use for finding tasks.
"""
if "Authorization" not in session.headers:
return "Please run the 'login' command first."
try:
response = session.get(f"{VIKUNJA_URL}/api/v1/tasks/search?query={query}")
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
return f"Error searching tasks: {e}"
@mcp.tool()
def add_task(project_id: int, title: str, description: str = ""):
"""
Adds a new task to a Vikunja project.
:param project_id: The ID of the project to add the task to.
:param title: The title of the new task.
:param description: An optional description for the task.
"""
if "Authorization" not in session.headers:
return "Please run the 'login' command first."
task_payload = {
"project_id": project_id,
"title": title,
"description": description
}
try:
response = session.post(
f"{VIKUNJA_URL}/api/v1/projects/{project_id}/tasks",
json=task_payload
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
return f"Error adding task: {e}"
if __name__ == "__main__":
print("--- Vikunja MCP Client ---")
print("Available commands: login, search_tasks, add_task, help, exit")
mcp.run()

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
fastmcp
requests