A remote, streamable-HTTP MCP server. Point any MCP client — Claude Code, Codex, or Claude.ai as a custom connector — at:
{ "pulse": {
"url": "https://pulse.transmit.work/api/mcp",
"headers": { "Authorization": "Bearer psk_..." }
} }
Return the authenticated user’s profile.
No parameters.
Returns Profile: id, name, email, role, team, experience, companyId, emailVerified, tools[].
The workspace’s plan and seat usage. Pending invitations count as occupied seats.
No parameters.
Returns { billingEnabled, plan, source, seats: { limit, occupied, active, pending, available }, recording: { restricted, userId }, projects: { limit, active }, capabilities, inGrace, graceEndsAt, freePeriodEndsAt, alwaysFree[], proOnly[] }. On the Free plan only the selected recording member can log or edit time; everyone else is view/export only. Writes that a plan doesn’t allow fail with 402 and a message starting “Plan limit:”.
pulse_list_entries
Read-only
List the caller’s own time entries, newest first, paginated.
Parameters
scope · "week" | "month" | "last_month"
Reporting period. Defaults to the current week (Mon–Sun).
limit · number
Max entries to return, 1–200. Default 50.
offset · number
Entries to skip, for pagination. Default 0.
Returns { scope, total, count, offset, limit, has_more, next_offset, items[] } — each item has id, date, category, categoryLabel, tool, project, description, start, end, durationMin, pauseMin, kind, source, note.
pulse_get_summary
Read-only
The caller’s balance for the period: minutes used vs. quota.
Parameters
scope · "week" | "month" | "last_month"
Reporting period. Defaults to the current week.
Returns { scope, usedMin, quotaMin, percentUsed, remainingMin, entryCount, timeUnit, categories[] } — categories[] is a per-category minutes breakdown, sorted descending.
pulse_list_categories
Read-only
List the workspace’s active activity categories.
No parameters.
Returns { items: [{ id, label, color }] }
pulse_update_category
WriteAdmin-only
Rename an activity category.
Parameters
category · string · required
Category id, or exact (case-insensitive) label.
label · string · required
New label.
Returns { ok: true, id, message }
pulse_list_projects
Read-only
List the projects assigned to the caller.
No parameters.
Returns { items: [{ id, name }] } — only projects assigned to the caller.
pulse_create_project
WriteAdmin-only
Create a new project on the workspace.
Parameters
name · string · required
Project name (e.g. "Migration"). Appended to the end of the active list.
Returns { ok: true, id, message } on success, or { isError: true } with a plain-text reason.
pulse_update_project
WriteAdmin-only
Rename a project. There’s no archive/delete tool for projects (or categories, or tools) — that’s an intentional, in-app-only action in Settings, not something an agent can do in one call.
Parameters
project · string · required
Project id, or exact (case-insensitive) name.
name · string
New name. Only fields you pass are changed.
Returns { ok: true, id, message }
pulse_list_members
Read-onlyAdmin-only
List workspace members.
No parameters.
Returns { items: [{ id, name, email, role, team, pending, emailVerified }] }. Errors for non-admin tokens.
Log a time entry on the caller’s own timesheet. Recorded directly and immediately visible — no approval step. Entries logged this way are tagged source: "agent".
Parameters
category · string · required
Prefer the readable label (e.g. "Dev") from pulse_list_categories — the id also works.
tool · string · required
Prefer the readable label (e.g. "Claude Code") from pulse_list_tools — the id also works.
description · string · required
What the work was.
durationMin · number · required
Duration in minutes.
date · string · required
YYYY-MM-DD — the day the work happened. Not defaulted, so a backfilled entry never gets silently dated to today.
start · string
Optional start time, HH:MM.
end · string
Optional end time, HH:MM.
note · string
Optional free-text note — e.g. a PR URL or issue id, for traceability.
project · string
Project label or id. Sets project attribution in the same call.
reviewId · string
If this row was reviewed with pulse_review_captures, its reviewId — records that the user approved it (and whether they edited it first) for calibration. Never affects whether the entry is logged.
Returns { ok: true, id, message: "Entry logged." }
Update fields on an existing entry owned by the caller. Only the fields you pass change.
Parameters
entry_id · string · required
The entry id, from pulse_list_entries.
category · string
New category — label or id.
tool · string
New tool — label or id.
project · string | null
New project — label or id; pass null to clear.
description · string
New description.
durationMin · number
New duration in minutes.
start · string | null
HH:MM, or null to clear.
end · string | null
HH:MM, or null to clear.
note · string | null
Or null to clear.
Returns { ok: true, id, message: "Entry updated." }
The two tools below are opt-in. An admin turns on Jev review under Settings → Lab — off by default. With it off, these tools don’t appear in tools/list at all, and pulse_review_captures returns { skipped: true, reason } rather than an error if called anyway (e.g. right after an admin turns it back off mid-session).
pulse_review_captures
Write
Get Jev’s independent, advisory read on a batch of time entries before showing them to the user for approval — before any of them are logged. This call writes nothing to the timesheet. Show the result next to each proposed row, then still wait for the user’s explicit approval — a recommendation: "approve" is advice, not approval. Pass the row’s reviewId to pulse_log_entry for rows the user approves, and report the rest via pulse_record_capture_decisions.
Parameters
entries · object[] · required
Up to 30 proposed time entries, not yet logged: date, durationMin, category, tool, description are required; start, end, project, note are optional. Each may also carry an evidence object — { commits?, prs?, repos?, sessions? } — with whatever real commit shas, PR URLs, repo names, or session titles/minutes back the row. Never invent evidence that isn’t there; an entry with none is scored on the row’s own content alone.
Returns { reviewer: "jev", advisory: true, note, items }. Each item: { index, reviewId, status: "ok" | "error", recommendation?, confidence?, summary?, issues?, error? }. index matches the position in the request’s entries array. recommendation is approve | review | reject; issues is up to a few { type, severity, message } objects. An item can come back status: "error" on its own (the evaluator failed for that row) without failing the whole call.
pulse_record_capture_decisions
Write
Report the rows a user dropped after reviewing proposed entries, so Pulse can measure how well Jev’s advice matched what the user actually decided (see scripts/review-metrics.ts in the repo). Approved rows are recorded automatically when their reviewId is passed to pulse_log_entry — this tool is only for the ones that weren’t. Changes no entries.
Parameters
dropped · string[] · required
reviewIds (from pulse_review_captures) of rows the user chose not to log — up to 30.
Returns { recorded: number } — how many of the reviewIds matched a review the caller owns that hadn’t already been closed by a decision.
The seven work-memory tools below are opt-in, and scoped by role. They’re off for new workspaces. An admin enables the feature under Settings → Lab → Work memory (Off / Admins only / Everyone), and sets separately, under Agent capture, whose agents may use these tools — so a workspace can let every engineer’s agent file suggestions while only admins review them. While a token’s role is excluded the tools don’t appear in tools/list at all (rather than appearing and failing), and the REST endpoints return 403 — or 404 when the feature is off for the whole workspace. If your agent can’t see them, those settings are why.
pulse_suggest_memory
Write
Propose something durable the agent noticed while working — a decision made, a constraint discovered, a migration completed. It lands as status: "suggested" for a human to confirm, edit, or dismiss in the app, so it is safe to offer one when unsure. Routine activity (typo fixes, running tests, ordinary commits) should never produce a memory — the timeline is already exhaustive; memory stays selective.
Parameters
type · string · required
decision | learning | outcome | milestone | blocker.
title · string · required
The decision or lesson itself, stated plainly.
summary · string · required
A sentence or two that still makes sense out of context.
detail · string
Longer context — alternatives weighed, caveats, links.
occurredOn · string · required
YYYY-MM-DD — the day it happened.
project · string
Project name or id. Omit for a workspace-level memory.
confidence · number
0-1 or 0-100.
entryIds · string[]
Ids of the caller’s own entries this came from, for provenance.
source · object
{ repo?, path, commit } — a note in a connected GitHub repo (see pulse_get_memory_repo). commit must be the full 40-character sha. Pulse checks the file exists at that commit and stores only the pointer, never the note. If GitHub can’t be reached the memory is still saved, marked unverified; a definite “not found” is rejected. Use this or sourceUrl, not both.
agent · string
Optional, self-reported name of the agent (e.g. “Claude Code”), up to 64 characters. Shown to reviewers as unverified.
model · string
Optional, self-reported model name, up to 64 characters. Unverified.
sessionId · string
Optional session or conversation id, up to 128 characters, so a reviewer can group memories from one session. Unverified.
Returns { ok: true, id, status: "suggested", message }
Save a memory directly as confirmed. Only for when the user explicitly asked to remember something (“remember that we chose Vercel”) — an inference the agent made on its own belongs in pulse_suggest_memory.
Parameters
Same as pulse_suggest_memory, minus
confidence.
Returns { ok: true, id, status: "confirmed", message }
pulse_list_memories
Read-only
The workspace’s durable knowledge, newest first. Returns confirmed memories by default, so an agent reading back gets settled decisions rather than untriaged guesses. Only confirmed memories are workspace-wide; suggestions stay visible to whoever captured them (and admins).
Parameters
status · string
confirmed (default) | suggested | dismissed | any.
type · string
Filter to one kind.
project · string
Project name or id.
from · string
Earliest occurredOn (YYYY-MM-DD).
to · string
Latest occurredOn (YYYY-MM-DD).
credential · string
Only memories written with this credential id (createdBy.agent.verified.credentialId).
agent · string
Only memories whose self-reported agent name matches (case-insensitive). Unverified.
limit · number
Default 50, max 200.
offset · number
For pagination.
Returns { total, count, offset, limit, has_more, next_offset, items } — each item carries its provenance: type, title, summary, detail, status, confidence, occurredOn, project, createdBy { userId, name, source, agent }, and entryIds. For agent-written memories createdBy.agent is { verified: { via, credentialId, credentialLabel }, claimed: { name, model, sessionId } }: verified is derived by Pulse from the token that wrote it (API token or OAuth client); claimed is whatever the agent said about itself and is unverified. agent is null for memories a person wrote.
pulse_search_memories
Read-only
Search across title, summary, and detail — for questions like “what did we learn about Supabase auth?”. Keyword matching always runs. If an admin has enabled Semantic search (Settings → Lab), results are also ranked by meaning across English and Japanese and each carries a similarity score (null for keyword-only hits). Rows without an index yet stay reachable by keyword. The calling model still judges relevance.
Parameters
query · string · required
Keywords or a natural-language question. Keywords always match; meaning also matches when Semantic search is on.
status · string
any (default) | confirmed | suggested | dismissed.
type · string
Filter to one kind.
project · string
Project name or id.
from · string
Earliest occurredOn (YYYY-MM-DD).
to · string
Latest occurredOn (YYYY-MM-DD).
includeSuperseded · boolean
Also return memories a confirmed newer one has replaced. Default false.
credential · string
Only memories written with this credential id.
agent · string
Only memories whose self-reported agent name matches (case-insensitive). Unverified.
limit · number
Default 25, max 200.
offset · number
For pagination.
Returns { query, total, count, offset, limit, has_more, next_offset, items }
Refine a memory the caller captured that a human hasn’t confirmed yet. Once confirmed it is the team’s record, and only an admin can change it.
Parameters
memory_id · string · required
The memory id, from pulse_list_memories.
summary · string
New summary.
detail · string | null
Or null to clear.
occurredOn · string
YYYY-MM-DD.
project · string | null
Name or id; null to clear.
confidence · number
0-1 or 0-100.
Returns { ok: true, id, message: "Memory updated." }
pulse_get_memory_repo
Read-only
Where this workspace keeps agent memory notes: the connected GitHub repo(s), the folder and file format to write in, and how to link a note to a suggestion. Read-only, and it returns no credentials. Agents write and push notes with git themselves; Pulse only checks that a cited file exists at a commit.
Returns { connected, repos: [{ repo, pathPrefix, project, status }], noteFormat, permalinkTemplate, howToSuggest }
pulse_dismiss_memory
Write
Retract a suggestion that turned out to be wrong. Works only on the caller’s own memories that nobody has confirmed yet, and sets status: "dismissed" rather than deleting anything.
Parameters
memory_id · string · required
The memory id.
Returns { ok: true, id, message: "Memory dismissed." }
There is no pulse_confirm_memory — by design. Confirming is what turns an agent’s inference into organizational truth that future agents read back as settled fact, so it stays a deliberate in-app action (the same way deleting an entry does). An agent can still retract its own untriaged suggestion with pulse_dismiss_memory. In the app, only the memory’s author or an admin can confirm it. Each memory records the token or OAuth client that wrote it; the agent, model and session labels an agent may send are stored as self-reported and never used for access decisions.
No delete tool exists, by design — every entry an agent writes stays visible and editable, never silently removed.