whoami
Who this MCP server is connected as: account email, API key name, granted scopes, server URL, and whether end-to-end-encrypted names can be decrypted. Call this first when a tool fails, to see which scopes are missing.
無需輸入參數。

com.pyunto由 pyunto.com 發布v0.4.0更新於 Nov 3, 2026
Read your Pyunto Time Management schedule and log time from an AI assistant. E2EE project planning.
把 AI 助理連接到 Pyunto Time Management 帳號,可讀取排程、彙總已記錄工時,並記錄或修改時間區塊與甘特圖任務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
參照 儲存庫 中的啟動說明。
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.
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.
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:
Result: mcp/dist/cli.js, the executable stdio server (dist/index.js
stays a side-effect-free module the tests can import).
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.
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.
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.
來源:mcp/README.md,提交 6add94b
Who this MCP server is connected as: account email, API key name, granted scopes, server URL, and whether end-to-end-encrypted names can be decrypted. Call this first when a tool fails, to see which scopes are missing.
無需輸入參數。
List every project the account can see, with id, name, colour and role (owner/editor/viewer). Use it to resolve a project name the user typed into the project_id other tools need. Requires the projects:read scope.
無需輸入參數。
List Gantt tasks (and subtasks) with their id, project, name and date range. Filter to one project with project_id. Use it to resolve a task name into the task_id that log_time takes. Requires the projects:read scope.
active_onproject_idThe individual time blocks logged between two dates (inclusive, max 92 days), with start/end times, duration, project, task and memo. This is the detailed schedule; use time_summary when you only need totals. Requires blocks:read.
date_to必填date_from必填Total hours logged between two dates (inclusive, max 92 days), grouped by project, by task, or by day. This is the tool to answer 'how much time did I spend on X' and to write a work log or diary entry. Requires record:read.
date_to必填group_bydate_from必填Record a block of worked time on the calendar. Writes to the user's real schedule, so confirm the project, date and times with them before calling it. Requires the blocks:write scope; for an end-to-end-encrypted project a memo additionally needs PYUNTO_TM_PASSWORD so it can be encrypted locally.
end必填date必填memostart必填task_idproject_id必填Change an already-recorded time block: its date, start/end times, memo, or the task it counts towards. Get block_id from list_time_blocks. Only the fields you pass change. Tell the user what the block currently says and what it will say before calling this. Requires the blocks:write scope; changing a memo on an end-to-end-encrypted project also needs PYUNTO_TM_PASSWORD, and project_id so the memo is encrypted under the right key.
enddatememostarttask_idblock_id必填project_idPermanently delete ONE recorded time block, along with any files attached to it. Before calling it you MUST show the user the block you are about to delete (date, start and end time, project, task and memo, from list_time_blocks) and get an explicit yes for that specific block. Never infer the block from a vague instruction, and never delete several blocks because the user described a range — confirm and delete them one at a time. A deleted block can be put back with restore_time_block for 14 days, after which it and its attachments are purged for good and cannot be recovered; say so when you report the deletion, and do not tell the user the deletion is irreversible. Requires the blocks:delete scope, which is separate from blocks:write and has to be granted deliberately.
block_id必填Time blocks that were deleted but can still be restored, newest first, each with the date it was deleted and the deadline for putting it back. Use it to find the block_id for restore_time_block when the user says they deleted something by mistake. Requires the blocks:read scope.
無需輸入參數。
Put a deleted time block back on the calendar, along with any files that were attached to it. Get block_id from list_deleted_time_blocks. Works only within the 14-day recovery window; after that the block is gone for good. Requires the blocks:write scope.
block_id必填Add a task to the Gantt chart — a piece of work with a start and end date, which is what time blocks are later logged against. Use this for work that spans days or longer; for time already worked use log_time instead. Writes to the user's real plan, so confirm the project, name and dates with them first. Requires the tasks:write scope; an end-to-end-encrypted project also needs PYUNTO_TM_PASSWORD so the name can be encrypted locally.
name必填end_date必填project_id必填start_date必填parent_task_idMark a Gantt task finished, or reopen it. The task stays on the chart, drawn dimmed — nothing is deleted. This is how a finished piece of work shows up on the plan. Get task_id from list_tasks. Requires the tasks:write scope.
task_id必填completedChange a task's name, dates, or whether it is archived. Only the fields you pass change. Moving the dates also moves every task that depends on this one, and the reply lists everything that moved — tell the user about those too. Archiving hides a task from every view and is reversible; there is deliberately no way to delete a task through this server, because that would detach the time already logged against it. Requires the tasks:write scope; renaming an end-to-end-encrypted project's task also needs PYUNTO_TM_PASSWORD.
nametask_id必填archivedend_datestart_dateSet how many hours a task should get in one calendar month. This is what the daily draft (the ✨ button) divides across the month's remaining workdays — a task with no target is skipped entirely, which is the usual reason the draft produces nothing. Requires the tasks:write scope.
hours必填task_id必填year_month必填已滿足適用檢查項的 90%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
npx -y @pyunto/tm-mcp # what an MCP client config runsnpm installnpm run build # both packagesnpm test # sdk crypto round-trips + 25 MCP tool checks{ "mcpServers": { "pyunto-tm": { "command": "npx", "args": ["-y", "@pyunto/tm-mcp"], "env": { "PYUNTO_TM_API_KEY": "ptm_…" } } }}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