heyhuman-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # heyhuman-mcp
2
+
3
+ MCP server for [AskHumanToWork](https://github.com/KuronokiCorp/AskHumanToWork) — the todo hub where **AI agents capture your
4
+ todos** (with due dates and "why this exists" provenance) and the system **reminds you until they're
5
+ done**.
6
+
7
+ This package is the stdio MCP connector. It talks to your AskHumanToWork server over its REST API.
8
+
9
+ ## Setup
10
+
11
+ 1. In the AskHumanToWork web app: **Settings → API tokens → Create token**. Copy the `tfa_...` token.
12
+ 2. Add the server to your MCP client:
13
+
14
+ **Claude Code**
15
+
16
+ ```bash
17
+ claude mcp add askhumantowork \
18
+ --env TODO_API_TOKEN=tfa_... \
19
+ --env TODO_API_URL=https://your-server.example.com \
20
+ -- npx -y heyhuman-mcp
21
+ ```
22
+
23
+ **Claude Desktop** (`claude_desktop_config.json`)
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "askhumantowork": {
29
+ "command": "npx",
30
+ "args": ["-y", "heyhuman-mcp"],
31
+ "env": {
32
+ "TODO_API_TOKEN": "tfa_...",
33
+ "TODO_API_URL": "https://your-server.example.com"
34
+ }
35
+ }
36
+ }
37
+ }
38
+ ```
39
+
40
+ Environment variables: `TODO_API_TOKEN` (required), `TODO_API_URL` (default `http://localhost:3000`),
41
+ `TODO_WEB_URL` (deep-link base, default `http://localhost:5173`), `TODO_AGENT_NAME` (shown as the
42
+ todo's provenance, default `mcp-stdio`).
43
+
44
+ Prefer a remote connection with no local install? AskHumanToWork also serves Streamable HTTP MCP at
45
+ `POST <server>/mcp` with `Authorization: Bearer <token>`.
46
+
47
+ ## Tools
48
+
49
+ `add_todo` · `list_todos` · `search_todos` · `update_todo` · `complete_todo` · `reschedule_todo` ·
50
+ `get_agenda` · `list_projects` · `list_integrations` · `resolve_time`
51
+
52
+ Natural-language due dates ("friday 5pm", "in 3 days") are resolved **server-side in your timezone**,
53
+ adds are idempotent (10-minute dedup window), and every AI-created todo carries `origin_context` so
54
+ you remember *why* it exists when the reminder fires.
55
+
56
+ Resources: `todo://agenda/today`, `todo://agenda/overdue`, `todo://projects`
57
+ Prompts: `capture-followups`, `review-my-todos`
package/dist/bin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
package/dist/bin.js ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * HeyHuman stdio MCP server — a thin HTTP client for the hosted API.
4
+ * No database, no local server required: it just needs your API token.
5
+ *
6
+ * Claude Desktop / Claude Code config:
7
+ * command: npx -y heyhuman-mcp
8
+ * env: TODO_API_TOKEN=tfa_... (create in the web app → Settings → API tokens)
9
+ * TODO_API_URL=... (optional — defaults to the hosted app)
10
+ */
11
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
12
+ import { createTodoMcpServer } from './tools.js';
13
+ import { RestTodoClient } from './client-rest.js';
14
+ /** Hosted API — the connector talks to this by default; no local stack needed. */
15
+ const DEFAULT_API_URL = 'https://askhumantowork--askhumantowork.asia-east1.hosted.app';
16
+ const token = process.env.TODO_API_TOKEN;
17
+ if (!token) {
18
+ console.error('TODO_API_TOKEN env var is required (create one in the web app → Settings → API tokens)');
19
+ process.exit(1);
20
+ }
21
+ const apiUrl = process.env.TODO_API_URL ?? DEFAULT_API_URL;
22
+ const webUrl = process.env.TODO_WEB_URL ?? apiUrl;
23
+ const agent = process.env.TODO_AGENT_NAME ?? 'mcp-stdio';
24
+ const client = new RestTodoClient(apiUrl, token, agent, webUrl);
25
+ const server = createTodoMcpServer(client);
26
+ const transport = new StdioServerTransport();
27
+ await server.connect(transport);
28
+ console.error(`HeyHuman MCP server running (stdio) → ${apiUrl}`);
29
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,kFAAkF;AAClF,MAAM,eAAe,GAAG,8DAA8D,CAAC;AAEvF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AACzC,IAAI,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,CAAC,KAAK,CAAC,wFAAwF,CAAC,CAAC;IACxG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,eAAe,CAAC;AAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC;AAClD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,WAAW,CAAC;AAEzD,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAChE,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAE3C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAChC,OAAO,CAAC,KAAK,CAAC,yCAAyC,MAAM,EAAE,CAAC,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { Agenda, Briefing, CreateTodoInput, ListTodosQuery, Project, Todo, UpdateTodoInput } from '@askhumantowork/shared';
2
+ import type { IntegrationInfo, SyncResult, TodoClient } from './client.js';
3
+ /**
4
+ * REST-backed client used by the stdio binary: every MCP tool call becomes an
5
+ * authenticated HTTP call to the AskHumanToWork API.
6
+ */
7
+ export declare class RestTodoClient implements TodoClient {
8
+ private apiUrl;
9
+ private token;
10
+ private agent;
11
+ private webUrl;
12
+ constructor(apiUrl: string, token: string, agent: string, webUrl: string);
13
+ webBaseUrl(): string;
14
+ agentName(): string;
15
+ private call;
16
+ addTodo(input: CreateTodoInput): Promise<{
17
+ todo: Todo;
18
+ deduplicated: boolean;
19
+ sync: SyncResult[];
20
+ }>;
21
+ listTodos(query: Partial<ListTodosQuery>): Promise<Todo[]>;
22
+ getTodo(id: string): Promise<Todo>;
23
+ updateTodo(id: string, input: UpdateTodoInput): Promise<Todo>;
24
+ completeTodo(id: string): Promise<Todo>;
25
+ getAgenda(): Promise<Agenda>;
26
+ getBriefing(): Promise<Briefing>;
27
+ listProjects(): Promise<Project[]>;
28
+ listIntegrations(): Promise<IntegrationInfo[]>;
29
+ resolveTime(text: string): Promise<{
30
+ iso: string;
31
+ display: string;
32
+ timezone: string;
33
+ } | null>;
34
+ }
35
+ //# sourceMappingURL=client-rest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-rest.d.ts","sourceRoot":"","sources":["../src/client-rest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EACN,QAAQ,EACR,eAAe,EACf,cAAc,EACd,OAAO,EACP,IAAI,EACJ,eAAe,EAChB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3E;;;GAGG;AACH,qBAAa,cAAe,YAAW,UAAU;IAE7C,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;gBAHN,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;IAGxB,UAAU;IAIV,SAAS;YAIK,IAAI;IAuBZ,OAAO,CAAC,KAAK,EAAE,eAAe;cACT,IAAI;sBAAgB,OAAO;cAAQ,UAAU,EAAE;;IAOpE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAU1D,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAI5B,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;IAIhC,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAIlC,gBAAgB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAY9C,WAAW,CAAC,IAAI,EAAE,MAAM;aACJ,MAAM;iBAAW,MAAM;kBAAY,MAAM;;CAMpE"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * REST-backed client used by the stdio binary: every MCP tool call becomes an
3
+ * authenticated HTTP call to the AskHumanToWork API.
4
+ */
5
+ export class RestTodoClient {
6
+ apiUrl;
7
+ token;
8
+ agent;
9
+ webUrl;
10
+ constructor(apiUrl, token, agent, webUrl) {
11
+ this.apiUrl = apiUrl;
12
+ this.token = token;
13
+ this.agent = agent;
14
+ this.webUrl = webUrl;
15
+ }
16
+ webBaseUrl() {
17
+ return this.webUrl;
18
+ }
19
+ agentName() {
20
+ return this.agent;
21
+ }
22
+ async call(method, path, body) {
23
+ const res = await fetch(`${this.apiUrl}${path}`, {
24
+ method,
25
+ headers: {
26
+ Authorization: `Bearer ${this.token}`,
27
+ 'Content-Type': 'application/json',
28
+ 'X-Agent-Name': this.agent,
29
+ },
30
+ body: body === undefined ? undefined : JSON.stringify(body),
31
+ });
32
+ if (!res.ok) {
33
+ let detail = `${res.status}`;
34
+ try {
35
+ const data = (await res.json());
36
+ if (data.error)
37
+ detail = data.error;
38
+ }
39
+ catch {
40
+ /* keep status */
41
+ }
42
+ throw new Error(detail);
43
+ }
44
+ return res.json();
45
+ }
46
+ async addTodo(input) {
47
+ return this.call('POST', '/api/todos', input);
48
+ }
49
+ async listTodos(query) {
50
+ const params = new URLSearchParams();
51
+ for (const [k, v] of Object.entries(query)) {
52
+ if (v === undefined)
53
+ continue;
54
+ params.set(k, Array.isArray(v) ? v.join(',') : String(v));
55
+ }
56
+ const data = await this.call('GET', `/api/todos?${params}`);
57
+ return data.todos;
58
+ }
59
+ async getTodo(id) {
60
+ return (await this.call('GET', `/api/todos/${id}`)).todo;
61
+ }
62
+ async updateTodo(id, input) {
63
+ return (await this.call('PATCH', `/api/todos/${id}`, input)).todo;
64
+ }
65
+ async completeTodo(id) {
66
+ return (await this.call('POST', `/api/todos/${id}/complete`)).todo;
67
+ }
68
+ async getAgenda() {
69
+ return this.call('GET', '/api/agenda');
70
+ }
71
+ async getBriefing() {
72
+ return this.call('GET', '/api/briefing');
73
+ }
74
+ async listProjects() {
75
+ return (await this.call('GET', '/api/projects')).projects;
76
+ }
77
+ async listIntegrations() {
78
+ const data = await this.call('GET', '/api/integrations');
79
+ return data.integrations.map((i) => ({
80
+ provider: i.provider,
81
+ displayName: i.displayName,
82
+ status: i.status,
83
+ capabilities: i.capabilities,
84
+ }));
85
+ }
86
+ async resolveTime(text) {
87
+ return this.call('POST', '/api/resolve-time', { text });
88
+ }
89
+ }
90
+ //# sourceMappingURL=client-rest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-rest.js","sourceRoot":"","sources":["../src/client-rest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { Agenda, Briefing, CreateTodoInput, ListTodosQuery, Project, Todo, UpdateTodoInput } from '@askhumantowork/shared';
2
+ export interface SyncResult {
3
+ provider: string;
4
+ status: 'queued' | 'skipped';
5
+ }
6
+ export interface IntegrationInfo {
7
+ provider: string;
8
+ displayName: string;
9
+ status: string;
10
+ capabilities: Record<string, boolean>;
11
+ }
12
+ /**
13
+ * Backend abstraction the MCP tools talk to. Two implementations:
14
+ * - RestTodoClient (stdio binary → remote REST API with a PAT)
15
+ * - CoreTodoClient (in-process, used by the /mcp HTTP transport in the API server)
16
+ * Keeping tools transport-agnostic means one source of truth for the MCP surface.
17
+ */
18
+ export interface TodoClient {
19
+ webBaseUrl(): string;
20
+ agentName(): string;
21
+ addTodo(input: CreateTodoInput): Promise<{
22
+ todo: Todo;
23
+ deduplicated: boolean;
24
+ sync: SyncResult[];
25
+ }>;
26
+ listTodos(query: Partial<ListTodosQuery>): Promise<Todo[]>;
27
+ getTodo(id: string): Promise<Todo>;
28
+ updateTodo(id: string, input: UpdateTodoInput): Promise<Todo>;
29
+ completeTodo(id: string): Promise<Todo>;
30
+ getAgenda(): Promise<Agenda>;
31
+ getBriefing(): Promise<Briefing>;
32
+ listProjects(): Promise<Project[]>;
33
+ listIntegrations(): Promise<IntegrationInfo[]>;
34
+ resolveTime(text: string): Promise<{
35
+ iso: string;
36
+ display: string;
37
+ timezone: string;
38
+ } | null>;
39
+ }
40
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EACN,QAAQ,EACR,eAAe,EACf,cAAc,EACd,OAAO,EACP,IAAI,EACJ,eAAe,EAChB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,IAAI,MAAM,CAAC;IACrB,SAAS,IAAI,MAAM,CAAC;IACpB,OAAO,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,YAAY,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAAC;IACpG,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACnC,gBAAgB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC/C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CAC/F"}
package/dist/client.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export * from './client.js';
2
+ export * from './client-rest.js';
3
+ export * from './tools.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './client.js';
2
+ export * from './client-rest.js';
3
+ export * from './tools.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { TodoClient } from './client.js';
3
+ export declare function createTodoMcpServer(client: TodoClient): McpServer;
4
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAmC9C,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAgTjE"}
package/dist/tools.js ADDED
@@ -0,0 +1,244 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ function ok(data) {
4
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
5
+ }
6
+ function fail(message) {
7
+ return { content: [{ type: 'text', text: `Error: ${message}` }], isError: true };
8
+ }
9
+ /** Compact wire form so agents can reason over lists cheaply. */
10
+ function compact(t) {
11
+ return {
12
+ id: t.id,
13
+ title: t.title,
14
+ due: t.dueAt,
15
+ status: t.status,
16
+ priority: t.priority,
17
+ project: t.projectName,
18
+ tags: t.tags.length ? t.tags : undefined,
19
+ source: t.source === 'ai' ? `ai (${t.createdByAgent ?? 'unknown'})` : 'human',
20
+ originContext: t.originContext ?? undefined,
21
+ repeats: t.recurrence?.display,
22
+ blockedReason: t.status === 'blocked' ? (t.blockedReason ?? 'no reason recorded') : undefined,
23
+ };
24
+ }
25
+ async function run(fn) {
26
+ try {
27
+ return await fn();
28
+ }
29
+ catch (err) {
30
+ return fail(err instanceof Error ? err.message : String(err));
31
+ }
32
+ }
33
+ export function createTodoMcpServer(client) {
34
+ const server = new McpServer({ name: 'heyhuman', version: '0.1.0' });
35
+ // ---------- Tools ----------
36
+ server.tool('add_todo', 'Add a todo to the user\'s list. Use this whenever the user should remember to do something later, ' +
37
+ 'or when you commit to a follow-up on their behalf. ALWAYS set a due date if one is stated or implied ' +
38
+ '(prefer due_natural — the server resolves it in the user\'s timezone, never do date math yourself). ' +
39
+ 'ALWAYS fill origin_context with one sentence on WHY this todo exists so the user remembers the context ' +
40
+ 'when reminded. The call is idempotent within 10 minutes (same title+due+project returns the existing todo).', {
41
+ title: z.string().max(200).describe('Short imperative title, e.g. "Deploy payments-service v2"'),
42
+ notes: z.string().max(10_000).optional().describe('Longer details, links, checklists'),
43
+ due_natural: z
44
+ .string()
45
+ .max(120)
46
+ .optional()
47
+ .describe('Due date in natural language, e.g. "friday 5pm", "in 3 days", "tomorrow morning". Preferred over due_at.'),
48
+ due_at: z.string().optional().describe('Absolute ISO 8601 due date. Only if you already have an exact instant.'),
49
+ project: z.string().max(100).optional().describe('Project name; fuzzy-matched to existing projects, created if new'),
50
+ priority: z.number().int().min(0).max(3).optional().describe('0=none 1=low 2=medium 3=high'),
51
+ tags: z.array(z.string().max(50)).max(20).optional(),
52
+ reminders: z.array(z.string()).max(10).optional()
53
+ .describe('Explicit reminder times (natural language or ISO). Omit for sensible defaults derived from the due date (1 day before, 1 hour before, at due, then daily overdue nudges).'),
54
+ origin_context: z.string().max(500).optional()
55
+ .describe('One sentence on WHY this todo exists, e.g. "You asked me to remind you after we found the flaky test." Strongly recommended.'),
56
+ repeat: z.string().max(80).optional()
57
+ .describe('Recurrence in natural language: "every day", "every monday", "every mon and thu", "every 2 weeks", "monthly". If no due date is given, the first occurrence is scheduled automatically. Completing an occurrence schedules the next one.'),
58
+ sync_to: z.array(z.enum(['ms-todo', 'google-tasks'])).optional()
59
+ .describe('Override which connected external apps mirror this todo. Omit to use the user\'s routing rules. Check list_integrations for what is connected.'),
60
+ }, async (args) => run(async () => {
61
+ const result = await client.addTodo({
62
+ title: args.title,
63
+ notes: args.notes,
64
+ dueNatural: args.due_natural,
65
+ dueAt: args.due_at,
66
+ project: args.project,
67
+ priority: args.priority,
68
+ tags: args.tags,
69
+ reminders: args.reminders,
70
+ originContext: args.origin_context,
71
+ repeat: args.repeat,
72
+ syncTo: args.sync_to,
73
+ });
74
+ return ok({
75
+ ...(result.deduplicated ? { note: 'Identical todo was created moments ago — returning it instead of duplicating.' } : {}),
76
+ todo: compact(result.todo),
77
+ link: `${client.webBaseUrl()}/t/${result.todo.id}`,
78
+ sync: result.sync,
79
+ });
80
+ }));
81
+ server.tool('list_todos', 'List the user\'s todos with filters. Use get_agenda instead for a "what\'s on my plate" overview.', {
82
+ status: z.enum(['open', 'doing', 'done', 'cancelled']).optional().describe('Default: all statuses'),
83
+ project: z.string().optional(),
84
+ due_before: z.string().optional().describe('ISO date — only todos due before this'),
85
+ overdue: z.boolean().optional().describe('Only overdue open todos'),
86
+ tags: z.array(z.string()).optional(),
87
+ source: z.enum(['human', 'ai']).optional().describe('Filter by who created the todo'),
88
+ limit: z.number().int().min(1).max(200).optional(),
89
+ }, async (args) => run(async () => {
90
+ const todos = await client.listTodos({
91
+ status: args.status,
92
+ project: args.project,
93
+ dueBefore: args.due_before,
94
+ overdue: args.overdue,
95
+ tags: args.tags,
96
+ source: args.source,
97
+ limit: args.limit ?? 50,
98
+ offset: 0,
99
+ });
100
+ return ok({ count: todos.length, todos: todos.map(compact) });
101
+ }));
102
+ server.tool('search_todos', 'Full-text search over todo titles and notes. Use when looking for a specific todo by content.', { query: z.string().min(1), limit: z.number().int().min(1).max(100).optional() }, async (args) => run(async () => {
103
+ const todos = await client.listTodos({ search: args.query, limit: args.limit ?? 20, offset: 0 });
104
+ return ok({ count: todos.length, todos: todos.map(compact) });
105
+ }));
106
+ server.tool('update_todo', 'Update a todo\'s fields (title, notes, due date, project, priority, tags, status). ' +
107
+ 'For marking done use complete_todo; for changing only the due date use reschedule_todo.', {
108
+ id: z.string().describe('Todo id (from add_todo/list_todos/search_todos)'),
109
+ title: z.string().max(200).optional(),
110
+ notes: z.string().max(10_000).optional(),
111
+ due_natural: z.string().max(120).optional().describe('New due date in natural language'),
112
+ clear_due: z.boolean().optional().describe('Remove the due date entirely'),
113
+ project: z.string().max(100).optional(),
114
+ priority: z.number().int().min(0).max(3).optional(),
115
+ tags: z.array(z.string()).optional(),
116
+ status: z.enum(['open', 'doing', 'blocked', 'done', 'cancelled']).optional()
117
+ .describe('Set "blocked" (with blocked_reason) when work cannot proceed — it will be surfaced in every future briefing until unblocked.'),
118
+ blocked_reason: z.string().max(500).optional()
119
+ .describe('WHY the todo is blocked, e.g. "waiting for App Review verdict". Set together with status "blocked"; cleared automatically when the status changes.'),
120
+ repeat: z.string().max(80).optional().describe('Set recurrence, e.g. "every friday"'),
121
+ clear_repeat: z.boolean().optional().describe('Stop this todo from repeating'),
122
+ }, async (args) => run(async () => {
123
+ const todo = await client.updateTodo(args.id, {
124
+ title: args.title,
125
+ notes: args.notes,
126
+ dueNatural: args.due_natural,
127
+ dueAt: args.clear_due ? null : undefined,
128
+ project: args.project,
129
+ priority: args.priority,
130
+ tags: args.tags,
131
+ status: args.status,
132
+ blockedReason: args.blocked_reason,
133
+ repeat: args.clear_repeat ? null : args.repeat,
134
+ });
135
+ return ok({ todo: compact(todo) });
136
+ }));
137
+ server.tool('complete_todo', 'Mark a todo as done. Cancels its pending reminders and mirrors completion to connected apps.', { id: z.string() }, async (args) => run(async () => {
138
+ const todo = await client.completeTodo(args.id);
139
+ return ok({ todo: compact(todo), note: 'Completed. Reminders cancelled.' });
140
+ }));
141
+ server.tool('reschedule_todo', 'Move a todo\'s due date. Reminders are recomputed automatically from the new date.', {
142
+ id: z.string(),
143
+ due_natural: z.string().max(120).describe('New due date in natural language, e.g. "next tuesday 3pm"'),
144
+ }, async (args) => run(async () => {
145
+ const todo = await client.updateTodo(args.id, { dueNatural: args.due_natural });
146
+ return ok({ todo: compact(todo) });
147
+ }));
148
+ server.tool('get_briefing', 'Call this FIRST, at the START of every session — before doing anything else with todos. ' +
149
+ 'It diffs the list against your previous check-in: what the user COMPLETED since then ' +
150
+ '(acknowledge their progress), what was newly added, what is BLOCKED and why (offer to help ' +
151
+ 'unblock), what is overdue, and nextSteps — the recommended order to start working. ' +
152
+ 'Use it to pick up exactly where things left off instead of re-reading the whole list.', {}, async () => run(async () => {
153
+ const b = await client.getBriefing();
154
+ return ok({
155
+ since: b.since,
156
+ timezone: b.timezone,
157
+ summary: b.summary,
158
+ completedSinceLastSession: b.completedSinceLastSession.map(compact),
159
+ addedSinceLastSession: b.addedSinceLastSession.map(compact),
160
+ blocked: b.blocked.map(compact),
161
+ overdue: b.overdue.map(compact),
162
+ nextSteps: b.nextSteps.map(compact),
163
+ });
164
+ }));
165
+ server.tool('get_agenda', 'The user\'s current agenda: overdue, due today, and next 7 days, in their timezone. ' +
166
+ 'For session start prefer get_briefing — it also tells you what changed since your last visit.', {}, async () => run(async () => {
167
+ const agenda = await client.getAgenda();
168
+ return ok({
169
+ date: agenda.date,
170
+ timezone: agenda.timezone,
171
+ summary: agenda.summary,
172
+ overdue: agenda.overdue.map(compact),
173
+ today: agenda.today.map(compact),
174
+ upcoming: agenda.upcoming.map(compact),
175
+ });
176
+ }));
177
+ server.tool('list_projects', 'List the user\'s projects (for matching a todo to the right project).', {}, async () => run(async () => ok({ projects: await client.listProjects() })));
178
+ server.tool('list_integrations', 'Which external todo apps (Microsoft To Do, Google Tasks, …) are connected, and their capabilities. ' +
179
+ 'Use before sync_to, or to answer "put this in my Microsoft list".', {}, async () => run(async () => ok({ integrations: await client.listIntegrations() })));
180
+ server.tool('resolve_time', 'Resolve a natural-language time ("next tuesday 3pm") to an absolute instant in the user\'s timezone. ' +
181
+ 'Usually unnecessary — add_todo/reschedule_todo accept due_natural directly.', { text: z.string().max(120) }, async (args) => run(async () => {
182
+ const resolved = await client.resolveTime(args.text);
183
+ return resolved ? ok(resolved) : fail(`could not parse "${args.text}"`);
184
+ }));
185
+ // ---------- Resources ----------
186
+ server.resource('agenda-today', 'todo://agenda/today', async (uri) => {
187
+ const agenda = await client.getAgenda();
188
+ return {
189
+ contents: [
190
+ {
191
+ uri: uri.href,
192
+ mimeType: 'application/json',
193
+ text: JSON.stringify({ summary: agenda.summary, overdue: agenda.overdue.map(compact), today: agenda.today.map(compact) }, null, 2),
194
+ },
195
+ ],
196
+ };
197
+ });
198
+ server.resource('agenda-overdue', 'todo://agenda/overdue', async (uri) => {
199
+ const agenda = await client.getAgenda();
200
+ return {
201
+ contents: [
202
+ { uri: uri.href, mimeType: 'application/json', text: JSON.stringify(agenda.overdue.map(compact), null, 2) },
203
+ ],
204
+ };
205
+ });
206
+ server.resource('projects', 'todo://projects', async (uri) => {
207
+ const projects = await client.listProjects();
208
+ return {
209
+ contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(projects, null, 2) }],
210
+ };
211
+ });
212
+ // ---------- Prompts ----------
213
+ server.prompt('capture-followups', 'Scan the conversation so far and capture every commitment or follow-up as todos.', async () => ({
214
+ messages: [
215
+ {
216
+ role: 'user',
217
+ content: {
218
+ type: 'text',
219
+ text: 'Review our conversation so far and identify every commitment, follow-up, or action item ' +
220
+ 'that I (the user) should do later — things I said I would do, things you recommended I do, ' +
221
+ 'and unresolved threads. For each one, call add_todo with a clear title, a due date if one was ' +
222
+ 'stated or reasonably implied (due_natural), the right project, and origin_context explaining ' +
223
+ 'where in our conversation it came from. Then show me a short list of what you captured.',
224
+ },
225
+ },
226
+ ],
227
+ }));
228
+ server.prompt('review-my-todos', 'Fetch the agenda and help the user triage: complete, reschedule, or drop.', async () => ({
229
+ messages: [
230
+ {
231
+ role: 'user',
232
+ content: {
233
+ type: 'text',
234
+ text: 'Call get_agenda, then walk me through my overdue and due-today items one by one. ' +
235
+ 'For each, ask whether I have done it (then complete_todo), want to reschedule ' +
236
+ '(then reschedule_todo), or want to drop it (then update_todo status=cancelled). ' +
237
+ 'Be brief; group obviously related items.',
238
+ },
239
+ },
240
+ ],
241
+ }));
242
+ return server;
243
+ }
244
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "heyhuman-mcp",
3
+ "version": "0.1.0",
4
+ "description": "HeyHuman MCP connector — let Claude (or any MCP client) capture todos into HeyHuman and remind you until they are done. Thin HTTP client for the hosted API; no database required.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "heyhuman-mcp": "./dist/bin.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ }
20
+ },
21
+ "keywords": [
22
+ "mcp",
23
+ "model-context-protocol",
24
+ "todo",
25
+ "claude",
26
+ "ai-agents",
27
+ "reminders"
28
+ ],
29
+ "license": "MIT",
30
+ "engines": {
31
+ "node": ">=20"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc -p tsconfig.json",
35
+ "typecheck": "tsc -p tsconfig.json --noEmit",
36
+ "test": "vitest run --passWithNoTests",
37
+ "prepublishOnly": "pnpm build",
38
+ "publish:npm": "bash -c 'set -a; . ../../.env 2>/dev/null; set +a; npm publish --access public \"--//registry.npmjs.org/:_authToken=$NPM_TOKEN\"'"
39
+ },
40
+ "dependencies": {
41
+ "@modelcontextprotocol/sdk": "^1.11.0",
42
+ "zod": "^3.24.1"
43
+ },
44
+ "devDependencies": {
45
+ "@askhumantowork/shared": "workspace:*",
46
+ "@types/node": "^22.10.2",
47
+ "typescript": "^5.7.2",
48
+ "vitest": "^2.1.8"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/KuronokiCorp/AskHumanToWork.git",
53
+ "directory": "packages/mcp"
54
+ },
55
+ "homepage": "https://github.com/KuronokiCorp/AskHumanToWork#readme",
56
+ "bugs": {
57
+ "url": "https://github.com/KuronokiCorp/AskHumanToWork/issues"
58
+ }
59
+ }