Tm Mcp

io.github.pyuntoPublished by GitHub account pyuntov0.3.4Updated Oct 24, 2026

Read your Pyunto Time Management schedule and log time from an AI assistant. E2EE project planning.

Overview

AI-generated overview

Connects an AI assistant to a Pyunto Time Management account to read schedules, summarize hours and log or edit time blocks and tasks.

What you can do
  • Check account identity, key scopes and decryption status
  • List projects and tasks, filtered by project or by a date the task covers
  • Read time blocks within a range of up to 92 days and summarize hours by project, task or date
  • Log, update and delete single time blocks, and list or restore recently deleted ones
  • Create, complete, reopen, rename, reschedule or archive Gantt tasks, and set a monthly target
When to use it
Useful when you track work in Pyunto Time Management and want an assistant to answer questions about your schedule and where the hours went, or to record and adjust time entries and task dates without opening the app.
Requirements
Runs locally over stdio, typically via npx, so Node.js is needed. Requires an API key in PYUNTO_TM_API_KEY (minted in the account settings); listing tools works without it. Optional PYUNTO_TM_BASE_URL for self-hosted instances, and PYUNTO_TM_PASSWORD or PYUNTO_TM_PASSWORD_FILE to decrypt end-to-end encrypted project and task names. Network access to the Pyunto TM API.
Before you install
The API key is a secret placed in the client config, and its scopes decide what the assistant can do; write scopes allow logging, editing and deleting time and changing task dates. The account password, if supplied, is used in memory to unwrap the private key for E2EE names; prefer the file variant over the environment variable. Deletion is single-block only and restorable for 14 days, but task deletion is not offered at all. Without a password, name fields come back empty.

Installation

In SourceWeft

  1. Open Tm Mcp in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

@pyunto/tm-mcp

MCP (Model Context Protocol) server for Pyunto Time Management. Connects Claude Code, Claude Desktop, Codex CLI, Cursor and any other MCP client to a Pyunto TM account so an assistant can read the schedule, summarise where the hours went, and log time.

User-facing setup instructions live at https://tm.pyunto.com/docs/mcp.en.md (日本語: https://tm.pyunto.com/docs/mcp.ja.md). This file is the developer view.

Tools

ToolScope
whoami — account, key name, scopes, decryption status—
list_projectsprojects:read
list_tasks (filter by project or by a date the task covers)projects:read
list_time_blocks (range ≤ 92 days)blocks:read
time_summary (grouped by project / task / date)record:read
log_time (writes)blocks:write
update_time_block (writes)blocks:write
delete_time_block — one id, restorable for 14 daysblocks:delete
list_deleted_time_blocks / restore_time_blockblocks:read / blocks:write
create_task — a Gantt task with start and end datestasks:write
complete_task — mark finished, or reopentasks:write
update_task — rename, move dates, archivetasks:write
set_monthly_target — the budget the daily draft divides uptasks:write

Every tool returns JSON as text. Failures come back as isError results whose message names the fix (missing scope, wrong key, locked E2EE) rather than throwing at the transport level — an agent can act on that, a stack trace it cannot.

Install

bash
npx -y @pyunto/tm-mcp        # what an MCP client config runs

Build from source

This package lives in an npm-workspaces repository together with the SDK it depends on; build from the repository root so the workspace link is used:

bash
npm installnpm run build                 # both packagesnpm test                      # sdk crypto round-trips + 25 MCP tool checks

Result: mcp/dist/cli.js, the executable stdio server (dist/index.js stays a side-effect-free module the tests can import).

Configuration

Environment only — MCP clients spawn the process and inject env from their config file.

The server starts without an API key and answers tools/list — a client or a directory can see what it offers before anyone signs up. Calling a tool without one returns the same guidance as an isError rather than an opaque 401, and whoami reports the missing key instead of failing.

VariableRequiredDefaultPurpose
PYUNTO_TM_API_KEYfor data—ptm_…, minted in Settings → Account → API keys. Listing the tools works without it
PYUNTO_TM_BASE_URLhttps://tm.pyunto.comSelf-hosted instances
PYUNTO_TM_PASSWORDnoneUnwraps the private key locally so E2EE names/memos decrypt
PYUNTO_TM_PASSWORD_FILEnoneSame, read from a file instead of the env
json
{  "mcpServers": {    "pyunto-tm": {      "command": "npx",      "args": ["-y", "@pyunto/tm-mcp"],      "env": { "PYUNTO_TM_API_KEY": "ptm_…" }    }  }}

How E2EE is handled

Content fields are encrypted in the user's browser; the server never holds the plaintext, and neither does this process by default. Given a password, the server's password-wrapped private key blob (GET /api/v1/keys, scope keys:read) is unwrapped here, in memory, and used to open each project's sealed DEK. The password is never transmitted and nothing is written to disk.

Without a password the server still answers everything schedule-shaped — ids, dates, times, durations, aggregates — and name fields come back empty with a NOTE: explaining why, so the model reports the limitation instead of inventing names.

Layout

src/index.ts     tool definitions + implementations + server wiringsrc/cli.ts       the bin: calls start()test/tools.mjs   stub /api/v1 server, exercises every tool and error pathtest/cli.mjs     spawns the built bin (directly and via symlink) over real MCP

callTool(name, args) is exported for tests; start() attaches the transport and is called only by cli.ts.

delete_time_block is deliberately single-id: no range or filter delete is exposed, because an automated caller getting a range wrong destroys an unbounded amount of data that has no restore path. Its tool description requires the model to show the user the exact block first and get a yes for that block.

There is no delete_task for the same reason, and a sharper one: removing a task detaches every block that logged time against it (tasks.id ON DELETE SET NULL) and orphans its subtasks, with nothing to restore from. update_task offers archive instead — the task leaves every view and can be brought back.

tasks:write is separate from blocks:write on purpose. Recording time against a plan and rewriting the plan are different powers; a key given to something that only logs work should not be able to move deadlines.

update_task returns an array. Moving a task's dates drags its dependents along, and the caller is told what else moved rather than discovering it on the next read.

Source: mcp/README.md at commit 6add94b

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v0.3.4LatestSep 29, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts