All work

Taskmind

Task platform where AI agents assign work and catch schedule conflicts through an MCP server.

Year
2025
Role
Backend, agents, deploys (team of 3)
Stack
NestJS, Prisma, PydanticAI, FastMCP
Links
Private code
AngularNestJS APIauth, usersPostgreSQLFastMCP serverPydanticAI x3Gemini

Highlighted boxes are my work. Teammates built the Angular app, most API feature modules, and the API's MCP client.

The project

Taskmind is a task platform with workspaces, projects, sprints, and lists. Its AI features assign tasks to team members and find schedule conflicts. We built it as a team of three for a university project. My teammates built the Angular app and most of the feature modules in the API. I built three parts: the API foundation, the agent service, and the deploys.

API foundation

I started the NestJS project and set up the parts that every module depends on:

Agent service

The AI features live in a separate Python service. It is a FastMCP server with three tools, and each tool runs a PydanticAI agent on Gemini 2.5 Flash:

taskmind ยท agent service
NestJS API
FastMCP server
PydanticAI agent
Gemini
spawn child process
connected over MCP
tools/call: task assignment
tasks, members, workloads
tools/call: conflict detection
tasks, members, deadlines
tools/call: conflict resolution
conflicts, tasks, members
run agent
prompt + output schema
structured output
matches the output type
one member per task, each with a reason
conflicts with type, tasks, people
reassignments, each with a reason
typed result

    The NestJS API starts the agent service as a child process. The command is configurable, so the same build runs on a laptop and on the server.

    The message labels describe each step. They are not the exact MCP payloads.

    Assign

    1. The NestJS API starts the agent service as a child process. The command is configurable, so the same build runs on a laptop and on the server.
    2. The API calls an MCP tool. Task assignment gives each task to one member, based on skill match, workload, priority, and due date.
    3. The tool runs a PydanticAI agent on Gemini 2.5 Flash, with a Pydantic output type.
    4. The model must return data that matches that type. PydanticAI checks it before the tool returns.
    5. The API gets typed results over MCP, not free text that it must parse.

    Detect

    1. The NestJS API starts the agent service as a child process. The command is configurable, so the same build runs on a laptop and on the server.
    2. The API calls an MCP tool. Conflict detection finds scheduling, technical, and resource conflicts.
    3. The tool runs a PydanticAI agent on Gemini 2.5 Flash, with a Pydantic output type.
    4. The model must return data that matches that type. PydanticAI checks it before the tool returns.
    5. The API gets typed results over MCP, not free text that it must parse.

    Resolve

    1. The NestJS API starts the agent service as a child process. The command is configurable, so the same build runs on a laptop and on the server.
    2. The API calls an MCP tool. Conflict resolution reassigns the tasks behind each conflict.
    3. The tool runs a PydanticAI agent on Gemini 2.5 Flash, with a Pydantic output type.
    4. The model must return data that matches that type. PydanticAI checks it before the tool returns.
    5. The API gets typed results over MCP, not free text that it must parse.

    Each agent has a Pydantic output type. The model must return data that matches the schema, so the API gets typed results, not free text that it must parse. The API starts the agent service as a child process and talks to it over MCP. I made the command configurable, so the same build works on a laptop and on the server.

    Deploys

    The API runs on Oracle Cloud under systemd, behind Caddy with TLS. I wrote the deploy scripts: build locally, upload with rsync, swap the release on the server, check health, and roll back on failure. These scripts later became the starting point for minideploy.