tododdle-mcp 2.0.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/.codex-plugin/plugin.json +29 -0
- package/LICENSE +21 -0
- package/README.md +193 -0
- package/dist/api-client.d.ts +30 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +99 -0
- package/dist/api-client.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +9 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +566 -0
- package/dist/server.js.map +1 -0
- package/examples/AGENTS.tododdle.md +11 -0
- package/package.json +62 -0
- package/skills/tododdle-workflow/SKILL.md +56 -0
- package/skills/tododdle-workflow/agents/openai.yaml +14 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tododdle",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Disciplined agent workflows for projects managed in ToDoddle.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "ToDoddle",
|
|
7
|
+
"url": "https://tododdle.com"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://tododdle.com",
|
|
10
|
+
"repository": "https://github.com/krffl/tododdle-mcp",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": ["project-management", "tasks", "time-tracking", "mcp"],
|
|
13
|
+
"skills": "./skills/",
|
|
14
|
+
"interface": {
|
|
15
|
+
"displayName": "ToDoddle",
|
|
16
|
+
"shortDescription": "Manage tracked work with project context",
|
|
17
|
+
"longDescription": "Use ToDoddle as the shared work ledger for project context, task execution, durable status updates, blockers, comments, and time tracking.",
|
|
18
|
+
"developerName": "ToDoddle",
|
|
19
|
+
"category": "Productivity",
|
|
20
|
+
"capabilities": ["Read", "Write"],
|
|
21
|
+
"websiteURL": "https://tododdle.com",
|
|
22
|
+
"defaultPrompt": [
|
|
23
|
+
"Review my ToDoddle work queue and recommend what to do next.",
|
|
24
|
+
"Read the project context and begin the relevant task.",
|
|
25
|
+
"Summarize progress and update the tracked work."
|
|
26
|
+
],
|
|
27
|
+
"brandColor": "#0F766E"
|
|
28
|
+
}
|
|
29
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ToDoddle
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# ToDoddle MCP Server
|
|
2
|
+
|
|
3
|
+
The official Model Context Protocol stdio server for [ToDoddle](https://tododdle.com). It gives MCP-compatible agents a bounded interface for project context, task management, comments, and time tracking through ToDoddle's hosted API.
|
|
4
|
+
|
|
5
|
+
The package contains no ToDoddle application or database code. It is a small stdio client that authenticates as an Agent Connection and calls the hosted API.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- Node.js 18 or newer
|
|
10
|
+
- A ToDoddle Agent Connection client ID and client secret
|
|
11
|
+
- Scopes and project grants configured for that Agent Connection in ToDoddle
|
|
12
|
+
|
|
13
|
+
## Configure
|
|
14
|
+
|
|
15
|
+
Create an Agent Connection in ToDoddle, grant it only the scopes and projects it needs, and copy its client ID and one-time client secret. Use a pinned package version so tool changes are deliberate.
|
|
16
|
+
|
|
17
|
+
### Codex
|
|
18
|
+
|
|
19
|
+
Add the server from a terminal:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
codex mcp add tododdle \
|
|
23
|
+
--env TODODDLE_CLIENT_ID=your_client_id \
|
|
24
|
+
--env TODODDLE_CLIENT_SECRET=your_client_secret \
|
|
25
|
+
-- npx -y tododdle-mcp@2.0.0
|
|
26
|
+
|
|
27
|
+
codex mcp list
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Codex desktop, the CLI, and the IDE extension share the MCP configuration in `~/.codex/config.toml`. For project-specific configuration, add the same server to `.codex/config.toml` in a trusted project. Restart the server after changing credentials or scopes.
|
|
31
|
+
|
|
32
|
+
See the [Codex MCP documentation](https://learn.chatgpt.com/docs/extend/mcp) for configuration and troubleshooting.
|
|
33
|
+
|
|
34
|
+
### Claude Code
|
|
35
|
+
|
|
36
|
+
Install the server for your user account so it is available across projects:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
claude mcp add tododdle --scope user \
|
|
40
|
+
--env TODODDLE_CLIENT_ID=your_client_id \
|
|
41
|
+
--env TODODDLE_CLIENT_SECRET=your_client_secret \
|
|
42
|
+
-- npx -y tododdle-mcp@2.0.0
|
|
43
|
+
|
|
44
|
+
claude mcp get tododdle
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Run `/mcp` inside Claude Code to inspect the connection. On native Windows, place `cmd /c` before `npx` in the command. See the [Claude Code MCP documentation](https://docs.anthropic.com/en/docs/claude-code/mcp) for scope options and diagnostics.
|
|
48
|
+
|
|
49
|
+
### Cursor
|
|
50
|
+
|
|
51
|
+
Add this configuration to `~/.cursor/mcp.json` for all projects, or to `.cursor/mcp.json` for one project:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"tododdle": {
|
|
57
|
+
"command": "npx",
|
|
58
|
+
"args": ["-y", "tododdle-mcp@2.0.0"],
|
|
59
|
+
"env": {
|
|
60
|
+
"TODODDLE_CLIENT_ID": "your_client_id",
|
|
61
|
+
"TODODDLE_CLIENT_SECRET": "your_client_secret"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Do not commit a project-level configuration containing real credentials. Restart Cursor after changing the configuration; ToDoddle tools will then be available to Agent. See the [Cursor MCP documentation](https://docs.cursor.com/context/model-context-protocol) for configuration and status controls.
|
|
69
|
+
|
|
70
|
+
For every client, `npx` downloads the package to npm's cache. Cloning ToDoddle or running a local ToDoddle service is not required.
|
|
71
|
+
|
|
72
|
+
## Codex Workflow Guidance
|
|
73
|
+
|
|
74
|
+
The MCP server provides capabilities; the optional `tododdle-workflow` skill provides a disciplined operating process for choosing and using them. It tells Codex to read project context first, reuse existing tasks, keep status and blockers accurate, leave durable comments, verify before completion, and avoid inventing time.
|
|
75
|
+
|
|
76
|
+
The npm package includes a Codex plugin containing this skill. Configure the MCP server first using the Codex instructions above, then add the ToDoddle plugin marketplace:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
codex plugin marketplace add krffl/tododdle-mcp
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Restart Codex, open the Plugins Directory, select **ToDoddle**, and install the plugin. Codex can invoke the skill automatically when a request concerns tracked work, or you can invoke it explicitly as `$tododdle-workflow`.
|
|
83
|
+
|
|
84
|
+
Installing the plugin does not create or expand ToDoddle credentials, scopes, or project grants. The skill declares the separately configured `tododdle` MCP server as a dependency.
|
|
85
|
+
|
|
86
|
+
### Repository Policy
|
|
87
|
+
|
|
88
|
+
When ToDoddle should be mandatory for one repository, merge the relevant rules from [`examples/AGENTS.tododdle.md`](examples/AGENTS.tododdle.md) into that repository's `AGENTS.md`. The policy makes tracking updates durable repository guidance; the skill remains the reusable workflow.
|
|
89
|
+
|
|
90
|
+
## Tools
|
|
91
|
+
|
|
92
|
+
### Read And Plan
|
|
93
|
+
|
|
94
|
+
- `list_projects`
|
|
95
|
+
- `get_project_context`
|
|
96
|
+
- `get_work_queue`
|
|
97
|
+
- `get_task`
|
|
98
|
+
- `get_project_brief`
|
|
99
|
+
- `list_project_artifacts`
|
|
100
|
+
- `get_project_artifact`
|
|
101
|
+
- `get_agent_inbox`
|
|
102
|
+
|
|
103
|
+
### Manage Tasks
|
|
104
|
+
|
|
105
|
+
- `create_task`
|
|
106
|
+
- `update_task`
|
|
107
|
+
- `transition_task`
|
|
108
|
+
- `move_task`
|
|
109
|
+
- `set_task_blocker`
|
|
110
|
+
- `add_task_comment`
|
|
111
|
+
- `acknowledge_agent_reply`
|
|
112
|
+
- `archive_task`
|
|
113
|
+
|
|
114
|
+
`archive_task` is destructive and requires client approval. Task deletion is intentionally unavailable.
|
|
115
|
+
|
|
116
|
+
### Track Time
|
|
117
|
+
|
|
118
|
+
- `get_active_time_entries`
|
|
119
|
+
- `list_project_time`
|
|
120
|
+
- `list_task_time`
|
|
121
|
+
- `start_task_timer`
|
|
122
|
+
- `stop_task_timer`
|
|
123
|
+
- `log_task_time`
|
|
124
|
+
- `update_time_entry`
|
|
125
|
+
- `archive_time_entry`
|
|
126
|
+
|
|
127
|
+
`archive_time_entry` is destructive and requires client approval.
|
|
128
|
+
|
|
129
|
+
### Manage Project Context
|
|
130
|
+
|
|
131
|
+
- `create_project_artifact`
|
|
132
|
+
- `update_project_artifact`
|
|
133
|
+
- `transition_project_artifact`
|
|
134
|
+
- `link_artifact_task`
|
|
135
|
+
- `add_artifact_comment`
|
|
136
|
+
|
|
137
|
+
The server also provides task, project, and project-artifact resource templates plus `triage_work` and `daily_status` prompts.
|
|
138
|
+
|
|
139
|
+
## Permissions
|
|
140
|
+
|
|
141
|
+
Tools never expand the Agent Connection's authority. Every request is checked against all three layers:
|
|
142
|
+
|
|
143
|
+
1. The Agent Connection's granted scopes.
|
|
144
|
+
2. Its granted projects.
|
|
145
|
+
3. The authorizing user's organization and project permissions.
|
|
146
|
+
|
|
147
|
+
Configure scopes and project grants in ToDoddle under **Agent Connections**. Scopes are not requested by or stored in this package.
|
|
148
|
+
|
|
149
|
+
Common scopes include:
|
|
150
|
+
|
|
151
|
+
- `projects:read` and `projects:write`
|
|
152
|
+
- `tasks:read` and `tasks:write`
|
|
153
|
+
- `context:read` and `context:write`
|
|
154
|
+
- `time:read` and `time:write`
|
|
155
|
+
|
|
156
|
+
## Environment
|
|
157
|
+
|
|
158
|
+
| Variable | Required | Default | Purpose |
|
|
159
|
+
| --- | --- | --- | --- |
|
|
160
|
+
| `TODODDLE_CLIENT_ID` | Yes | None | Agent Connection identifier |
|
|
161
|
+
| `TODODDLE_CLIENT_SECRET` | Yes | None | Agent Connection secret |
|
|
162
|
+
|
|
163
|
+
Tokens are held in memory only and refreshed automatically. The client secret is sent only to ToDoddle's hosted token endpoint. Server diagnostics go to stderr so stdout remains reserved for MCP JSON-RPC.
|
|
164
|
+
|
|
165
|
+
## Development
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm install
|
|
169
|
+
npm run type-check
|
|
170
|
+
npm test
|
|
171
|
+
npm pack --dry-run
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Run the MCP package from source:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
TODODDLE_CLIENT_ID=... \
|
|
178
|
+
TODODDLE_CLIENT_SECRET=... \
|
|
179
|
+
npm run dev
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The npm `prepack` lifecycle builds `dist/` automatically. `prepublishOnly` runs the complete package test before publication.
|
|
183
|
+
|
|
184
|
+
## Release Safety
|
|
185
|
+
|
|
186
|
+
- Review `npm pack --dry-run` and verify that only `dist/`, `README.md`, `LICENSE`, and package metadata are present.
|
|
187
|
+
- Publish from a tagged release with npm trusted publishing/provenance where available.
|
|
188
|
+
- Treat tool removal, renaming, or incompatible input changes as major releases.
|
|
189
|
+
- Keep generated ToDoddle connection snippets pinned to a tested package version.
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { McpConfig } from './config.js';
|
|
2
|
+
export declare class ToDoddleApiError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly code: string;
|
|
5
|
+
readonly details?: unknown;
|
|
6
|
+
constructor(status: number, code: string, message: string, details?: unknown);
|
|
7
|
+
}
|
|
8
|
+
export interface ToDoddleApi {
|
|
9
|
+
get(path: string, query?: Record<string, string | number | boolean | undefined>): Promise<Record<string, unknown>>;
|
|
10
|
+
post(path: string, body: unknown, idempotencyKey?: string): Promise<Record<string, unknown>>;
|
|
11
|
+
put(path: string, body: unknown): Promise<Record<string, unknown>>;
|
|
12
|
+
patch(path: string, body: unknown): Promise<Record<string, unknown>>;
|
|
13
|
+
delete(path: string, body: unknown): Promise<Record<string, unknown>>;
|
|
14
|
+
}
|
|
15
|
+
export declare class ToDoddleApiClient implements ToDoddleApi {
|
|
16
|
+
private readonly config;
|
|
17
|
+
private accessToken;
|
|
18
|
+
private tokenExpiresAt;
|
|
19
|
+
constructor(config: McpConfig);
|
|
20
|
+
private getAccessToken;
|
|
21
|
+
private request;
|
|
22
|
+
private readPayload;
|
|
23
|
+
private toError;
|
|
24
|
+
get(path: string, query?: Record<string, string | number | boolean | undefined>): Promise<Record<string, unknown>>;
|
|
25
|
+
post(path: string, body: unknown, idempotencyKey?: string): Promise<Record<string, unknown>>;
|
|
26
|
+
put(path: string, body: unknown): Promise<Record<string, unknown>>;
|
|
27
|
+
patch(path: string, body: unknown): Promise<Record<string, unknown>>;
|
|
28
|
+
delete(path: string, body: unknown): Promise<Record<string, unknown>>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAS7C,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO;IAJ5B,YACW,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,OAAO,CAAC,EAAE,OAAO,EAI3B;CACF;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CACD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,GAC5D,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7F,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvE;AAED,qBAAa,iBAAkB,YAAW,WAAW;IAIvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAK;IAE3B,YAA6B,MAAM,EAAE,SAAS,EAAI;YAEpC,cAAc;YAwBd,OAAO;YAmCP,WAAW;IAOzB,OAAO,CAAC,OAAO;IAaf,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,oCAE9E;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,oCAExD;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,oCAE9B;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,oCAEhC;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,oCAEjC;CACF"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const TODODDLE_ORIGIN = 'https://www.tododdle.com';
|
|
2
|
+
export class ToDoddleApiError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
code;
|
|
5
|
+
details;
|
|
6
|
+
constructor(status, code, message, details) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.details = details;
|
|
11
|
+
this.name = 'ToDoddleApiError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class ToDoddleApiClient {
|
|
15
|
+
config;
|
|
16
|
+
accessToken = null;
|
|
17
|
+
tokenExpiresAt = 0;
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.config = config;
|
|
20
|
+
}
|
|
21
|
+
async getAccessToken() {
|
|
22
|
+
if (this.accessToken && Date.now() < this.tokenExpiresAt - 30_000)
|
|
23
|
+
return this.accessToken;
|
|
24
|
+
const form = new URLSearchParams({
|
|
25
|
+
grant_type: 'client_credentials',
|
|
26
|
+
client_id: this.config.clientId,
|
|
27
|
+
client_secret: this.config.clientSecret,
|
|
28
|
+
});
|
|
29
|
+
const response = await fetch(`${TODODDLE_ORIGIN}/api/external/oauth/token`, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
32
|
+
body: form,
|
|
33
|
+
});
|
|
34
|
+
const payload = await this.readPayload(response);
|
|
35
|
+
if (!response.ok)
|
|
36
|
+
throw this.toError(response.status, payload);
|
|
37
|
+
const token = payload;
|
|
38
|
+
if (!token.access_token || !token.expires_in)
|
|
39
|
+
throw new Error('Token endpoint returned an invalid response');
|
|
40
|
+
this.accessToken = token.access_token;
|
|
41
|
+
this.tokenExpiresAt = Date.now() + token.expires_in * 1000;
|
|
42
|
+
return token.access_token;
|
|
43
|
+
}
|
|
44
|
+
async request(method, path, body, query, idempotencyKey, retry = true) {
|
|
45
|
+
const url = new URL(`${TODODDLE_ORIGIN}${path}`);
|
|
46
|
+
Object.entries(query || {}).forEach(([key, value]) => {
|
|
47
|
+
if (value !== undefined)
|
|
48
|
+
url.searchParams.set(key, String(value));
|
|
49
|
+
});
|
|
50
|
+
const token = await this.getAccessToken();
|
|
51
|
+
const response = await fetch(url, {
|
|
52
|
+
method,
|
|
53
|
+
headers: {
|
|
54
|
+
authorization: `Bearer ${token}`,
|
|
55
|
+
...(body !== undefined ? { 'content-type': 'application/json' } : {}),
|
|
56
|
+
...(idempotencyKey ? { 'idempotency-key': idempotencyKey } : {}),
|
|
57
|
+
},
|
|
58
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
59
|
+
});
|
|
60
|
+
if (response.status === 401 && retry) {
|
|
61
|
+
this.accessToken = null;
|
|
62
|
+
this.tokenExpiresAt = 0;
|
|
63
|
+
return this.request(method, path, body, query, idempotencyKey, false);
|
|
64
|
+
}
|
|
65
|
+
const payload = await this.readPayload(response);
|
|
66
|
+
if (!response.ok)
|
|
67
|
+
throw this.toError(response.status, payload);
|
|
68
|
+
return payload;
|
|
69
|
+
}
|
|
70
|
+
async readPayload(response) {
|
|
71
|
+
const payload = await response.json();
|
|
72
|
+
return payload && typeof payload === 'object'
|
|
73
|
+
? payload
|
|
74
|
+
: { value: payload };
|
|
75
|
+
}
|
|
76
|
+
toError(status, payload) {
|
|
77
|
+
return new ToDoddleApiError(status, typeof payload.error === 'string' ? payload.error : 'server_error', typeof payload.message === 'string'
|
|
78
|
+
? payload.message
|
|
79
|
+
: typeof payload.error_description === 'string'
|
|
80
|
+
? payload.error_description
|
|
81
|
+
: `ToDoddle request failed (${status})`, payload.details);
|
|
82
|
+
}
|
|
83
|
+
get(path, query) {
|
|
84
|
+
return this.request('GET', path, undefined, query);
|
|
85
|
+
}
|
|
86
|
+
post(path, body, idempotencyKey) {
|
|
87
|
+
return this.request('POST', path, body, undefined, idempotencyKey);
|
|
88
|
+
}
|
|
89
|
+
put(path, body) {
|
|
90
|
+
return this.request('PUT', path, body);
|
|
91
|
+
}
|
|
92
|
+
patch(path, body) {
|
|
93
|
+
return this.request('PATCH', path, body);
|
|
94
|
+
}
|
|
95
|
+
delete(path, body) {
|
|
96
|
+
return this.request('DELETE', path, body);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAOnD,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAE9B,MAAM;IACN,IAAI;IAEJ,OAAO;IAJlB,YACW,MAAc,EACd,IAAY,EACrB,OAAe,EACN,OAAiB;QAE1B,KAAK,CAAC,OAAO,CAAC,CAAC;sBALN,MAAM;oBACN,IAAI;uBAEJ,OAAO;QAGhB,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAaD,MAAM,OAAO,iBAAiB;IAIC,MAAM;IAH3B,WAAW,GAAkB,IAAI,CAAC;IAClC,cAAc,GAAG,CAAC,CAAC;IAE3B,YAA6B,MAAiB;sBAAjB,MAAM;IAAc,CAAC;IAE1C,KAAK,CAAC,cAAc;QAC1B,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,cAAc,GAAG,MAAM;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC;QAE3F,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC;YAC/B,UAAU,EAAE,oBAAoB;YAChC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC/B,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;SACxC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,eAAe,2BAA2B,EAAE;YAC1E,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE/D,MAAM,KAAK,GAAG,OAAmC,CAAC;QAClD,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,UAAU;YAC1C,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC;QACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;QAC3D,OAAO,KAAK,CAAC,YAAY,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,IAAY,EACZ,IAAc,EACd,KAA6D,EAC7D,cAAuB,EACvB,KAAK,GAAG,IAAI;QAEZ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,eAAe,GAAG,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACnD,IAAI,KAAK,KAAK,SAAS;gBAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM;YACN,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrE,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACjE;YACD,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC5D,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;YACrC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/D,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,QAAkB;QAC1C,MAAM,OAAO,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/C,OAAO,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;YAC3C,CAAC,CAAE,OAAmC;YACtC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IACzB,CAAC;IAEO,OAAO,CAAC,MAAc,EAAE,OAAgC;QAC9D,OAAO,IAAI,gBAAgB,CACzB,MAAM,EACN,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,EAClE,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;YACjC,CAAC,CAAC,OAAO,CAAC,OAAO;YACjB,CAAC,CAAC,OAAO,OAAO,CAAC,iBAAiB,KAAK,QAAQ;gBAC7C,CAAC,CAAC,OAAO,CAAC,iBAAiB;gBAC3B,CAAC,CAAC,4BAA4B,MAAM,GAAG,EAC3C,OAAO,CAAC,OAAO,CAChB,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,IAAY,EAAE,KAA6D;QAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,CAAC,IAAY,EAAE,IAAa,EAAE,cAAuB;QACvD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IACrE,CAAC;IAED,GAAG,CAAC,IAAY,EAAE,IAAa;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAY,EAAE,IAAa;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,IAAa;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;CACF"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,aAAa,CAAC,WAAW,GAAE,MAAM,CAAC,UAAwB,GAAG,SAAS,CASrF"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function loadMcpConfig(environment = process.env) {
|
|
2
|
+
const clientId = environment.TODODDLE_CLIENT_ID;
|
|
3
|
+
const clientSecret = environment.TODODDLE_CLIENT_SECRET;
|
|
4
|
+
if (!clientId || !clientSecret) {
|
|
5
|
+
throw new Error('TODODDLE_CLIENT_ID and TODODDLE_CLIENT_SECRET are required');
|
|
6
|
+
}
|
|
7
|
+
return { clientId, clientSecret };
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,aAAa,CAAC,WAAW,GAAsB,OAAO,CAAC,GAAG;IACxE,MAAM,QAAQ,GAAG,WAAW,CAAC,kBAAkB,CAAC;IAChD,MAAM,YAAY,GAAG,WAAW,CAAC,sBAAsB,CAAC;IAExD,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { ToDoddleApiClient } from './api-client.js';
|
|
4
|
+
import { loadMcpConfig } from './config.js';
|
|
5
|
+
import { createToDoddleMcpServer } from './server.js';
|
|
6
|
+
async function main() {
|
|
7
|
+
const server = createToDoddleMcpServer(new ToDoddleApiClient(loadMcpConfig()));
|
|
8
|
+
await server.connect(new StdioServerTransport());
|
|
9
|
+
console.error('ToDoddle MCP server connected over stdio');
|
|
10
|
+
}
|
|
11
|
+
main().catch((error) => {
|
|
12
|
+
console.error('ToDoddle MCP server failed:', error instanceof Error ? error.message : error);
|
|
13
|
+
process.exitCode = 1;
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,uBAAuB,CAAC,IAAI,iBAAiB,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IAC/E,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;AAC5D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAEtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA2CnD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS,CAiyBnE"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
const statusSchema = z.enum([
|
|
5
|
+
'TODO',
|
|
6
|
+
'IN_PROGRESS',
|
|
7
|
+
'REVIEW',
|
|
8
|
+
'COMPLETE',
|
|
9
|
+
'REJECTED',
|
|
10
|
+
'NEED_MORE_INFO',
|
|
11
|
+
'CANNOT_REPLICATE',
|
|
12
|
+
]);
|
|
13
|
+
const prioritySchema = z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']);
|
|
14
|
+
const taskKindSchema = z.enum(['TASK', 'EPIC', 'BUG', 'RESEARCH', 'ACTION_ITEM']);
|
|
15
|
+
const artifactTypeSchema = z.enum([
|
|
16
|
+
'BRIEF',
|
|
17
|
+
'SPEC',
|
|
18
|
+
'PROPOSAL',
|
|
19
|
+
'DECISION',
|
|
20
|
+
'PROCESS',
|
|
21
|
+
'RESEARCH',
|
|
22
|
+
'MEETING_PACKET',
|
|
23
|
+
'RETROSPECTIVE',
|
|
24
|
+
]);
|
|
25
|
+
const artifactStatusSchema = z.enum(['DRAFT', 'IN_REVIEW', 'APPROVED', 'SUPERSEDED', 'ARCHIVED']);
|
|
26
|
+
const commentKindSchema = z.enum([
|
|
27
|
+
'DISCUSSION',
|
|
28
|
+
'STATUS_UPDATE',
|
|
29
|
+
'QUESTION',
|
|
30
|
+
'DECISION',
|
|
31
|
+
'HANDOFF',
|
|
32
|
+
]);
|
|
33
|
+
const expectedUpdatedAtSchema = z
|
|
34
|
+
.string()
|
|
35
|
+
.datetime({ offset: true })
|
|
36
|
+
.describe('updatedAt from the latest task read');
|
|
37
|
+
function toolResult(value) {
|
|
38
|
+
return {
|
|
39
|
+
content: [{ type: 'text', text: JSON.stringify(value, null, 2) }],
|
|
40
|
+
structuredContent: value,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function createToDoddleMcpServer(api) {
|
|
44
|
+
const server = new McpServer({ name: 'tododdle', version: '2.0.0' });
|
|
45
|
+
server.registerTool('list_projects', {
|
|
46
|
+
description: 'List projects accessible through this Agent Connection.',
|
|
47
|
+
inputSchema: z.object({
|
|
48
|
+
search: z.string().optional(),
|
|
49
|
+
page: z.number().int().min(1).default(1),
|
|
50
|
+
limit: z.number().int().min(1).max(100).default(50),
|
|
51
|
+
}),
|
|
52
|
+
annotations: {
|
|
53
|
+
readOnlyHint: true,
|
|
54
|
+
destructiveHint: false,
|
|
55
|
+
idempotentHint: true,
|
|
56
|
+
openWorldHint: false,
|
|
57
|
+
},
|
|
58
|
+
}, async (input) => toolResult(await api.get('/api/external/projects', input)));
|
|
59
|
+
server.registerTool('get_project_context', {
|
|
60
|
+
description: 'Get bounded project-plan and section context for task planning.',
|
|
61
|
+
inputSchema: z.object({ projectId: z.string().min(1) }),
|
|
62
|
+
annotations: {
|
|
63
|
+
readOnlyHint: true,
|
|
64
|
+
destructiveHint: false,
|
|
65
|
+
idempotentHint: true,
|
|
66
|
+
openWorldHint: false,
|
|
67
|
+
},
|
|
68
|
+
}, async ({ projectId }) => toolResult(await api.get(`/api/external/projects/${projectId}/context`)));
|
|
69
|
+
server.registerTool('get_work_queue', {
|
|
70
|
+
description: 'Get active, overdue, or unassigned work with optional project, status, and search filters.',
|
|
71
|
+
inputSchema: z.object({
|
|
72
|
+
view: z.enum(['tasks', 'overdue', 'unassigned']).default('tasks'),
|
|
73
|
+
projectId: z.string().optional(),
|
|
74
|
+
status: statusSchema.optional(),
|
|
75
|
+
search: z.string().optional(),
|
|
76
|
+
limit: z.number().int().min(1).max(100).default(50),
|
|
77
|
+
cursor: z.string().datetime({ offset: true }).optional(),
|
|
78
|
+
}),
|
|
79
|
+
annotations: {
|
|
80
|
+
readOnlyHint: true,
|
|
81
|
+
destructiveHint: false,
|
|
82
|
+
idempotentHint: true,
|
|
83
|
+
openWorldHint: false,
|
|
84
|
+
},
|
|
85
|
+
}, async (input) => toolResult(await api.get('/api/external/work-queue', input)));
|
|
86
|
+
server.registerTool('get_task', {
|
|
87
|
+
description: 'Get complete task context including comments and blocker information.',
|
|
88
|
+
inputSchema: z.object({ taskId: z.string().min(1) }),
|
|
89
|
+
annotations: {
|
|
90
|
+
readOnlyHint: true,
|
|
91
|
+
destructiveHint: false,
|
|
92
|
+
idempotentHint: true,
|
|
93
|
+
openWorldHint: false,
|
|
94
|
+
},
|
|
95
|
+
}, async ({ taskId }) => toolResult(await api.get(`/api/external/tasks/${taskId}`)));
|
|
96
|
+
server.registerTool('create_task', {
|
|
97
|
+
description: 'Create a task in an active project plan section.',
|
|
98
|
+
inputSchema: z.object({
|
|
99
|
+
projectId: z.string().min(1),
|
|
100
|
+
planId: z.string().min(1),
|
|
101
|
+
sectionId: z.string().min(1),
|
|
102
|
+
title: z.string().min(1),
|
|
103
|
+
description: z.string().optional(),
|
|
104
|
+
priority: prioritySchema.optional(),
|
|
105
|
+
dueDate: z.string().datetime({ offset: true }).optional(),
|
|
106
|
+
assigneeId: z.string().optional(),
|
|
107
|
+
blockedByTaskId: z.string().optional(),
|
|
108
|
+
kind: taskKindSchema.optional(),
|
|
109
|
+
parentTaskId: z.string().optional(),
|
|
110
|
+
idempotencyKey: z.string().min(8).optional(),
|
|
111
|
+
}),
|
|
112
|
+
annotations: {
|
|
113
|
+
readOnlyHint: false,
|
|
114
|
+
destructiveHint: false,
|
|
115
|
+
idempotentHint: true,
|
|
116
|
+
openWorldHint: false,
|
|
117
|
+
},
|
|
118
|
+
}, async ({ idempotencyKey, ...body }) => toolResult(await api.post('/api/external/tasks', body, idempotencyKey || randomUUID())));
|
|
119
|
+
server.registerTool('update_task', {
|
|
120
|
+
description: 'Update editable task fields. Requires the latest updatedAt value to prevent overwriting newer changes.',
|
|
121
|
+
inputSchema: z.object({
|
|
122
|
+
taskId: z.string().min(1),
|
|
123
|
+
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
124
|
+
title: z.string().min(1).optional(),
|
|
125
|
+
description: z.string().nullable().optional(),
|
|
126
|
+
priority: prioritySchema.optional(),
|
|
127
|
+
dueDate: z.string().datetime({ offset: true }).nullable().optional(),
|
|
128
|
+
assigneeId: z.string().nullable().optional(),
|
|
129
|
+
kind: taskKindSchema.optional(),
|
|
130
|
+
parentTaskId: z.string().nullable().optional(),
|
|
131
|
+
}),
|
|
132
|
+
annotations: {
|
|
133
|
+
readOnlyHint: false,
|
|
134
|
+
destructiveHint: false,
|
|
135
|
+
idempotentHint: true,
|
|
136
|
+
openWorldHint: false,
|
|
137
|
+
},
|
|
138
|
+
}, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}`, body)));
|
|
139
|
+
server.registerTool('transition_task', {
|
|
140
|
+
description: 'Transition a task to a canonical status.',
|
|
141
|
+
inputSchema: z.object({
|
|
142
|
+
taskId: z.string().min(1),
|
|
143
|
+
status: statusSchema,
|
|
144
|
+
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
145
|
+
}),
|
|
146
|
+
annotations: {
|
|
147
|
+
readOnlyHint: false,
|
|
148
|
+
destructiveHint: false,
|
|
149
|
+
idempotentHint: true,
|
|
150
|
+
openWorldHint: false,
|
|
151
|
+
},
|
|
152
|
+
}, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}`, body)));
|
|
153
|
+
server.registerTool('move_task', {
|
|
154
|
+
description: 'Move a task to an active section and position in the same project.',
|
|
155
|
+
inputSchema: z.object({
|
|
156
|
+
taskId: z.string().min(1),
|
|
157
|
+
sectionId: z.string().min(1),
|
|
158
|
+
position: z.number().int().min(0),
|
|
159
|
+
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
160
|
+
}),
|
|
161
|
+
annotations: {
|
|
162
|
+
readOnlyHint: false,
|
|
163
|
+
destructiveHint: false,
|
|
164
|
+
idempotentHint: true,
|
|
165
|
+
openWorldHint: false,
|
|
166
|
+
},
|
|
167
|
+
}, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}/move`, body)));
|
|
168
|
+
server.registerTool('set_task_blocker', {
|
|
169
|
+
description: 'Set or clear the active same-project task blocking this task.',
|
|
170
|
+
inputSchema: z.object({
|
|
171
|
+
taskId: z.string().min(1),
|
|
172
|
+
blockedByTaskId: z.string().nullable(),
|
|
173
|
+
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
174
|
+
}),
|
|
175
|
+
annotations: {
|
|
176
|
+
readOnlyHint: false,
|
|
177
|
+
destructiveHint: false,
|
|
178
|
+
idempotentHint: true,
|
|
179
|
+
openWorldHint: false,
|
|
180
|
+
},
|
|
181
|
+
}, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}`, body)));
|
|
182
|
+
server.registerTool('add_task_comment', {
|
|
183
|
+
description: 'Add an implementation note, finding, decision, or completion evidence to a task.',
|
|
184
|
+
inputSchema: z.object({
|
|
185
|
+
taskId: z.string().min(1),
|
|
186
|
+
content: z.string().min(1),
|
|
187
|
+
kind: commentKindSchema.default('DISCUSSION'),
|
|
188
|
+
replyToCommentId: z.string().min(1).optional(),
|
|
189
|
+
idempotencyKey: z.string().min(8).optional(),
|
|
190
|
+
}),
|
|
191
|
+
annotations: {
|
|
192
|
+
readOnlyHint: false,
|
|
193
|
+
destructiveHint: false,
|
|
194
|
+
idempotentHint: true,
|
|
195
|
+
openWorldHint: false,
|
|
196
|
+
},
|
|
197
|
+
}, async ({ taskId, idempotencyKey, ...body }) => toolResult(await api.post(`/api/external/tasks/${taskId}/comments`, body, idempotencyKey || randomUUID())));
|
|
198
|
+
server.registerTool('get_agent_inbox', {
|
|
199
|
+
description: 'List human or agent replies to comments created by this Agent Connection.',
|
|
200
|
+
inputSchema: z.object({
|
|
201
|
+
cursor: z.string().min(1).optional(),
|
|
202
|
+
limit: z.number().int().min(1).max(100).default(25),
|
|
203
|
+
unacknowledgedOnly: z.boolean().default(true),
|
|
204
|
+
}),
|
|
205
|
+
annotations: {
|
|
206
|
+
readOnlyHint: true,
|
|
207
|
+
destructiveHint: false,
|
|
208
|
+
idempotentHint: true,
|
|
209
|
+
openWorldHint: false,
|
|
210
|
+
},
|
|
211
|
+
}, async (input) => toolResult(await api.get('/api/external/agent-inbox', input)));
|
|
212
|
+
server.registerTool('acknowledge_agent_reply', {
|
|
213
|
+
description: 'Mark one inbox reply as handled by this Agent Connection.',
|
|
214
|
+
inputSchema: z.object({ commentId: z.string().min(1) }),
|
|
215
|
+
annotations: {
|
|
216
|
+
readOnlyHint: false,
|
|
217
|
+
destructiveHint: false,
|
|
218
|
+
idempotentHint: true,
|
|
219
|
+
openWorldHint: false,
|
|
220
|
+
},
|
|
221
|
+
}, async ({ commentId }) => toolResult(await api.post(`/api/external/agent-inbox/${commentId}/acknowledge`, {})));
|
|
222
|
+
server.registerTool('archive_task', {
|
|
223
|
+
description: 'Archive a task and clear dependent blocker relationships. Requires explicit human approval.',
|
|
224
|
+
inputSchema: z.object({
|
|
225
|
+
taskId: z.string().min(1),
|
|
226
|
+
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
227
|
+
}),
|
|
228
|
+
annotations: {
|
|
229
|
+
readOnlyHint: false,
|
|
230
|
+
destructiveHint: true,
|
|
231
|
+
idempotentHint: true,
|
|
232
|
+
openWorldHint: false,
|
|
233
|
+
},
|
|
234
|
+
}, async ({ taskId, expectedUpdatedAt }) => toolResult(await api.patch(`/api/external/tasks/${taskId}/archive`, {
|
|
235
|
+
archived: true,
|
|
236
|
+
expectedUpdatedAt,
|
|
237
|
+
})));
|
|
238
|
+
server.registerTool('get_active_time_entries', {
|
|
239
|
+
description: 'List the current user’s active timers across granted projects.',
|
|
240
|
+
inputSchema: z.object({}),
|
|
241
|
+
annotations: {
|
|
242
|
+
readOnlyHint: true,
|
|
243
|
+
destructiveHint: false,
|
|
244
|
+
idempotentHint: true,
|
|
245
|
+
openWorldHint: false,
|
|
246
|
+
},
|
|
247
|
+
}, async () => toolResult(await api.get('/api/external/time-entries/active')));
|
|
248
|
+
server.registerTool('list_project_time', {
|
|
249
|
+
description: 'List bounded time entries and exact and rounded totals for a project.',
|
|
250
|
+
inputSchema: z.object({
|
|
251
|
+
projectId: z.string().min(1),
|
|
252
|
+
userId: z.string().optional(),
|
|
253
|
+
taskId: z.string().optional(),
|
|
254
|
+
startedFrom: z.string().datetime({ offset: true }).optional(),
|
|
255
|
+
startedTo: z.string().datetime({ offset: true }).optional(),
|
|
256
|
+
billable: z.boolean().optional(),
|
|
257
|
+
invoiced: z.boolean().optional(),
|
|
258
|
+
cursor: z.string().optional(),
|
|
259
|
+
limit: z.number().int().min(1).max(100).default(50),
|
|
260
|
+
}),
|
|
261
|
+
annotations: {
|
|
262
|
+
readOnlyHint: true,
|
|
263
|
+
destructiveHint: false,
|
|
264
|
+
idempotentHint: true,
|
|
265
|
+
openWorldHint: false,
|
|
266
|
+
},
|
|
267
|
+
}, async ({ projectId, ...query }) => toolResult(await api.get(`/api/external/projects/${projectId}/time-entries`, query)));
|
|
268
|
+
server.registerTool('list_task_time', {
|
|
269
|
+
description: 'List bounded time entries and totals for one task.',
|
|
270
|
+
inputSchema: z.object({
|
|
271
|
+
projectId: z.string().min(1),
|
|
272
|
+
taskId: z.string().min(1),
|
|
273
|
+
cursor: z.string().optional(),
|
|
274
|
+
limit: z.number().int().min(1).max(100).default(50),
|
|
275
|
+
}),
|
|
276
|
+
annotations: {
|
|
277
|
+
readOnlyHint: true,
|
|
278
|
+
destructiveHint: false,
|
|
279
|
+
idempotentHint: true,
|
|
280
|
+
openWorldHint: false,
|
|
281
|
+
},
|
|
282
|
+
}, async ({ projectId, taskId, ...query }) => toolResult(await api.get(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries`, query)));
|
|
283
|
+
server.registerTool('start_task_timer', {
|
|
284
|
+
description: 'Start a live timer on an active task. Overlapping timers are allowed.',
|
|
285
|
+
inputSchema: z.object({
|
|
286
|
+
projectId: z.string().min(1),
|
|
287
|
+
taskId: z.string().min(1),
|
|
288
|
+
startedAt: z.string().datetime({ offset: true }).optional(),
|
|
289
|
+
note: z.string().max(2000).optional(),
|
|
290
|
+
billable: z.boolean().optional(),
|
|
291
|
+
idempotencyKey: z.string().min(8).optional(),
|
|
292
|
+
}),
|
|
293
|
+
annotations: {
|
|
294
|
+
readOnlyHint: false,
|
|
295
|
+
destructiveHint: false,
|
|
296
|
+
idempotentHint: true,
|
|
297
|
+
openWorldHint: false,
|
|
298
|
+
},
|
|
299
|
+
}, async ({ projectId, taskId, idempotencyKey, startedAt, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries`, { ...body, startedAt: startedAt ?? new Date().toISOString() }, idempotencyKey || randomUUID())));
|
|
300
|
+
server.registerTool('stop_task_timer', {
|
|
301
|
+
description: 'Stop an active task timer using optimistic concurrency.',
|
|
302
|
+
inputSchema: z.object({
|
|
303
|
+
projectId: z.string().min(1),
|
|
304
|
+
taskId: z.string().min(1),
|
|
305
|
+
timeEntryId: z.string().min(1),
|
|
306
|
+
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
307
|
+
endedAt: z.string().datetime({ offset: true }).optional(),
|
|
308
|
+
}),
|
|
309
|
+
annotations: {
|
|
310
|
+
readOnlyHint: false,
|
|
311
|
+
destructiveHint: false,
|
|
312
|
+
idempotentHint: true,
|
|
313
|
+
openWorldHint: false,
|
|
314
|
+
},
|
|
315
|
+
}, async ({ projectId, taskId, timeEntryId, endedAt, expectedUpdatedAt }) => toolResult(await api.post(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries/${timeEntryId}/stop`, { endedAt: endedAt ?? new Date().toISOString(), expectedUpdatedAt })));
|
|
316
|
+
server.registerTool('log_task_time', {
|
|
317
|
+
description: 'Log a completed historical interval against a task.',
|
|
318
|
+
inputSchema: z.object({
|
|
319
|
+
projectId: z.string().min(1),
|
|
320
|
+
taskId: z.string().min(1),
|
|
321
|
+
startedAt: z.string().datetime({ offset: true }),
|
|
322
|
+
endedAt: z.string().datetime({ offset: true }),
|
|
323
|
+
note: z.string().max(2000).optional(),
|
|
324
|
+
billable: z.boolean().optional(),
|
|
325
|
+
idempotencyKey: z.string().min(8).optional(),
|
|
326
|
+
}),
|
|
327
|
+
annotations: {
|
|
328
|
+
readOnlyHint: false,
|
|
329
|
+
destructiveHint: false,
|
|
330
|
+
idempotentHint: true,
|
|
331
|
+
openWorldHint: false,
|
|
332
|
+
},
|
|
333
|
+
}, async ({ projectId, taskId, idempotencyKey, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries`, body, idempotencyKey || randomUUID())));
|
|
334
|
+
server.registerTool('update_time_entry', {
|
|
335
|
+
description: 'Correct a time interval, note, or billable flag using optimistic concurrency.',
|
|
336
|
+
inputSchema: z.object({
|
|
337
|
+
projectId: z.string().min(1),
|
|
338
|
+
taskId: z.string().min(1),
|
|
339
|
+
timeEntryId: z.string().min(1),
|
|
340
|
+
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
341
|
+
startedAt: z.string().datetime({ offset: true }).optional(),
|
|
342
|
+
endedAt: z.string().datetime({ offset: true }).nullable().optional(),
|
|
343
|
+
note: z.string().max(2000).nullable().optional(),
|
|
344
|
+
billable: z.boolean().optional(),
|
|
345
|
+
}),
|
|
346
|
+
annotations: {
|
|
347
|
+
readOnlyHint: false,
|
|
348
|
+
destructiveHint: false,
|
|
349
|
+
idempotentHint: true,
|
|
350
|
+
openWorldHint: false,
|
|
351
|
+
},
|
|
352
|
+
}, async ({ projectId, taskId, timeEntryId, ...body }) => toolResult(await api.patch(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries/${timeEntryId}`, body)));
|
|
353
|
+
server.registerTool('archive_time_entry', {
|
|
354
|
+
description: 'Archive an incorrect time entry. Requires explicit human approval.',
|
|
355
|
+
inputSchema: z.object({
|
|
356
|
+
projectId: z.string().min(1),
|
|
357
|
+
taskId: z.string().min(1),
|
|
358
|
+
timeEntryId: z.string().min(1),
|
|
359
|
+
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
360
|
+
}),
|
|
361
|
+
annotations: {
|
|
362
|
+
readOnlyHint: false,
|
|
363
|
+
destructiveHint: true,
|
|
364
|
+
idempotentHint: true,
|
|
365
|
+
openWorldHint: false,
|
|
366
|
+
},
|
|
367
|
+
}, async ({ projectId, taskId, timeEntryId, expectedUpdatedAt }) => toolResult(await api.delete(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries/${timeEntryId}`, { expectedUpdatedAt })));
|
|
368
|
+
server.registerTool('get_project_brief', {
|
|
369
|
+
description: 'Read the canonical project brief before planning or changing work.',
|
|
370
|
+
inputSchema: z.object({ projectId: z.string().min(1) }),
|
|
371
|
+
annotations: {
|
|
372
|
+
readOnlyHint: true,
|
|
373
|
+
destructiveHint: false,
|
|
374
|
+
idempotentHint: true,
|
|
375
|
+
openWorldHint: false,
|
|
376
|
+
},
|
|
377
|
+
}, async ({ projectId }) => toolResult(await api.get(`/api/external/projects/${projectId}/brief`)));
|
|
378
|
+
server.registerTool('list_project_artifacts', {
|
|
379
|
+
description: 'List bounded project specifications, decisions, proposals, research, processes, and meeting context.',
|
|
380
|
+
inputSchema: z.object({
|
|
381
|
+
projectId: z.string().min(1),
|
|
382
|
+
search: z.string().optional(),
|
|
383
|
+
type: artifactTypeSchema.optional(),
|
|
384
|
+
status: artifactStatusSchema.optional(),
|
|
385
|
+
page: z.number().int().min(1).default(1),
|
|
386
|
+
limit: z.number().int().min(1).max(100).default(25),
|
|
387
|
+
}),
|
|
388
|
+
annotations: {
|
|
389
|
+
readOnlyHint: true,
|
|
390
|
+
destructiveHint: false,
|
|
391
|
+
idempotentHint: true,
|
|
392
|
+
openWorldHint: false,
|
|
393
|
+
},
|
|
394
|
+
}, async ({ projectId, ...query }) => toolResult(await api.get(`/api/external/projects/${projectId}/artifacts`, query)));
|
|
395
|
+
server.registerTool('get_project_artifact', {
|
|
396
|
+
description: 'Get complete Markdown, relationships, comments, and task links for one project artifact.',
|
|
397
|
+
inputSchema: z.object({ projectId: z.string().min(1), artifactId: z.string().min(1) }),
|
|
398
|
+
annotations: {
|
|
399
|
+
readOnlyHint: true,
|
|
400
|
+
destructiveHint: false,
|
|
401
|
+
idempotentHint: true,
|
|
402
|
+
openWorldHint: false,
|
|
403
|
+
},
|
|
404
|
+
}, async ({ projectId, artifactId }) => toolResult(await api.get(`/api/external/projects/${projectId}/artifacts/${artifactId}`)));
|
|
405
|
+
server.registerTool('create_project_artifact', {
|
|
406
|
+
description: 'Create a typed Markdown artifact in a project. PRDs use the SPEC type.',
|
|
407
|
+
inputSchema: z.object({
|
|
408
|
+
projectId: z.string().min(1),
|
|
409
|
+
type: artifactTypeSchema,
|
|
410
|
+
title: z.string().min(1),
|
|
411
|
+
summary: z.string().nullable().optional(),
|
|
412
|
+
content: z.string().optional(),
|
|
413
|
+
ownerId: z.string().optional(),
|
|
414
|
+
metadata: z.record(z.unknown()).optional(),
|
|
415
|
+
changeNote: z.string().optional(),
|
|
416
|
+
idempotencyKey: z.string().min(8).optional(),
|
|
417
|
+
}),
|
|
418
|
+
annotations: {
|
|
419
|
+
readOnlyHint: false,
|
|
420
|
+
destructiveHint: false,
|
|
421
|
+
idempotentHint: true,
|
|
422
|
+
openWorldHint: false,
|
|
423
|
+
},
|
|
424
|
+
}, async ({ projectId, idempotencyKey, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/artifacts`, body, idempotencyKey || randomUUID())));
|
|
425
|
+
server.registerTool('update_project_artifact', {
|
|
426
|
+
description: 'Update artifact Markdown or metadata using optimistic concurrency. Editing approved content returns it to draft.',
|
|
427
|
+
inputSchema: z.object({
|
|
428
|
+
projectId: z.string().min(1),
|
|
429
|
+
artifactId: z.string().min(1),
|
|
430
|
+
expectedUpdatedAt: z.string().datetime({ offset: true }),
|
|
431
|
+
title: z.string().min(1).optional(),
|
|
432
|
+
summary: z.string().nullable().optional(),
|
|
433
|
+
content: z.string().optional(),
|
|
434
|
+
ownerId: z.string().optional(),
|
|
435
|
+
metadata: z.record(z.unknown()).optional(),
|
|
436
|
+
changeNote: z.string().optional(),
|
|
437
|
+
}),
|
|
438
|
+
annotations: {
|
|
439
|
+
readOnlyHint: false,
|
|
440
|
+
destructiveHint: false,
|
|
441
|
+
idempotentHint: true,
|
|
442
|
+
openWorldHint: false,
|
|
443
|
+
},
|
|
444
|
+
}, async ({ projectId, artifactId, ...body }) => toolResult(await api.patch(`/api/external/projects/${projectId}/artifacts/${artifactId}`, body)));
|
|
445
|
+
server.registerTool('transition_project_artifact', {
|
|
446
|
+
description: 'Submit, approve, supersede, archive, or return a project artifact to draft.',
|
|
447
|
+
inputSchema: z.object({
|
|
448
|
+
projectId: z.string().min(1),
|
|
449
|
+
artifactId: z.string().min(1),
|
|
450
|
+
status: artifactStatusSchema,
|
|
451
|
+
expectedUpdatedAt: z.string().datetime({ offset: true }),
|
|
452
|
+
changeNote: z.string().optional(),
|
|
453
|
+
}),
|
|
454
|
+
annotations: {
|
|
455
|
+
readOnlyHint: false,
|
|
456
|
+
destructiveHint: false,
|
|
457
|
+
idempotentHint: true,
|
|
458
|
+
openWorldHint: false,
|
|
459
|
+
},
|
|
460
|
+
}, async ({ projectId, artifactId, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/artifacts/${artifactId}/transition`, body)));
|
|
461
|
+
server.registerTool('link_artifact_task', {
|
|
462
|
+
description: 'Link same-project execution work to the context it implements, informs, evidences, or came from.',
|
|
463
|
+
inputSchema: z.object({
|
|
464
|
+
projectId: z.string().min(1),
|
|
465
|
+
artifactId: z.string().min(1),
|
|
466
|
+
taskId: z.string().min(1),
|
|
467
|
+
type: z
|
|
468
|
+
.enum(['RELATED', 'IMPLEMENTS', 'INFORMS', 'EVIDENCE', 'ACTION_FROM'])
|
|
469
|
+
.default('RELATED'),
|
|
470
|
+
}),
|
|
471
|
+
annotations: {
|
|
472
|
+
readOnlyHint: false,
|
|
473
|
+
destructiveHint: false,
|
|
474
|
+
idempotentHint: true,
|
|
475
|
+
openWorldHint: false,
|
|
476
|
+
},
|
|
477
|
+
}, async ({ projectId, artifactId, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/artifacts/${artifactId}/task-links`, body, randomUUID())));
|
|
478
|
+
server.registerTool('add_artifact_comment', {
|
|
479
|
+
description: 'Add or reply to a typed comment on project context. Attachments are not supported.',
|
|
480
|
+
inputSchema: z.object({
|
|
481
|
+
projectId: z.string().min(1),
|
|
482
|
+
artifactId: z.string().min(1),
|
|
483
|
+
content: z.string().min(1),
|
|
484
|
+
kind: commentKindSchema.default('DISCUSSION'),
|
|
485
|
+
replyToCommentId: z.string().min(1).optional(),
|
|
486
|
+
idempotencyKey: z.string().min(8).optional(),
|
|
487
|
+
}),
|
|
488
|
+
annotations: {
|
|
489
|
+
readOnlyHint: false,
|
|
490
|
+
destructiveHint: false,
|
|
491
|
+
idempotentHint: true,
|
|
492
|
+
openWorldHint: false,
|
|
493
|
+
},
|
|
494
|
+
}, async ({ projectId, artifactId, idempotencyKey, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/artifacts/${artifactId}/comments`, body, idempotencyKey || randomUUID())));
|
|
495
|
+
server.registerResource('task', new ResourceTemplate('tododdle://tasks/{taskId}', { list: undefined }), {
|
|
496
|
+
title: 'ToDoddle task',
|
|
497
|
+
description: 'Complete task context by ID.',
|
|
498
|
+
mimeType: 'application/json',
|
|
499
|
+
}, async (uri, variables) => ({
|
|
500
|
+
contents: [
|
|
501
|
+
{
|
|
502
|
+
uri: uri.href,
|
|
503
|
+
mimeType: 'application/json',
|
|
504
|
+
text: JSON.stringify(await api.get(`/api/external/tasks/${String(variables.taskId)}`), null, 2),
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
}));
|
|
508
|
+
server.registerResource('project', new ResourceTemplate('tododdle://projects/{projectId}', { list: undefined }), {
|
|
509
|
+
title: 'ToDoddle project context',
|
|
510
|
+
description: 'Bounded project-plan and section context by project ID.',
|
|
511
|
+
mimeType: 'application/json',
|
|
512
|
+
}, async (uri, variables) => ({
|
|
513
|
+
contents: [
|
|
514
|
+
{
|
|
515
|
+
uri: uri.href,
|
|
516
|
+
mimeType: 'application/json',
|
|
517
|
+
text: JSON.stringify(await api.get(`/api/external/projects/${String(variables.projectId)}/context`), null, 2),
|
|
518
|
+
},
|
|
519
|
+
],
|
|
520
|
+
}));
|
|
521
|
+
server.registerResource('project-artifact', new ResourceTemplate('tododdle://projects/{projectId}/artifacts/{artifactId}', {
|
|
522
|
+
list: undefined,
|
|
523
|
+
}), {
|
|
524
|
+
title: 'ToDoddle project artifact',
|
|
525
|
+
description: 'Complete project context artifact by project and artifact ID.',
|
|
526
|
+
mimeType: 'application/json',
|
|
527
|
+
}, async (uri, variables) => ({
|
|
528
|
+
contents: [
|
|
529
|
+
{
|
|
530
|
+
uri: uri.href,
|
|
531
|
+
mimeType: 'application/json',
|
|
532
|
+
text: JSON.stringify(await api.get(`/api/external/projects/${String(variables.projectId)}/artifacts/${String(variables.artifactId)}`), null, 2),
|
|
533
|
+
},
|
|
534
|
+
],
|
|
535
|
+
}));
|
|
536
|
+
server.registerPrompt('triage_work', {
|
|
537
|
+
description: 'Review active work and identify the most important next actions.',
|
|
538
|
+
argsSchema: { projectId: z.string().optional() },
|
|
539
|
+
}, ({ projectId }) => ({
|
|
540
|
+
messages: [
|
|
541
|
+
{
|
|
542
|
+
role: 'user',
|
|
543
|
+
content: {
|
|
544
|
+
type: 'text',
|
|
545
|
+
text: `${projectId ? `Read get_project_context for project ${projectId}, then ` : ''}use get_work_queue${projectId ? ` for that project` : ''}. Identify overdue, blocked, and unassigned tasks in light of project intent. Propose updates before making destructive changes.`,
|
|
546
|
+
},
|
|
547
|
+
},
|
|
548
|
+
],
|
|
549
|
+
}));
|
|
550
|
+
server.registerPrompt('daily_status', {
|
|
551
|
+
description: 'Summarize current work state for a human review.',
|
|
552
|
+
argsSchema: { projectId: z.string().optional() },
|
|
553
|
+
}, ({ projectId }) => ({
|
|
554
|
+
messages: [
|
|
555
|
+
{
|
|
556
|
+
role: 'user',
|
|
557
|
+
content: {
|
|
558
|
+
type: 'text',
|
|
559
|
+
text: `${projectId ? `Read get_project_context for project ${projectId}. ` : ''}Review current, overdue, and recently updated work${projectId ? ' for that project' : ''}. Summarize progress against intended outcomes, blockers, risks, decisions, and next actions with task links.`,
|
|
560
|
+
},
|
|
561
|
+
},
|
|
562
|
+
],
|
|
563
|
+
}));
|
|
564
|
+
return server;
|
|
565
|
+
}
|
|
566
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# ToDoddle Work Ledger
|
|
2
|
+
|
|
3
|
+
- Use the `tododdle` MCP server as this repository's authoritative work ledger.
|
|
4
|
+
- At the start of substantial work, identify the ToDoddle project, read its brief and project context, and find the existing task before creating another.
|
|
5
|
+
- Keep the task's status, section, assignee, priority, due date, parent, and blocker relationship accurate when the implementation changes them.
|
|
6
|
+
- Transition the relevant task to the active status when work begins. Mark it `COMPLETE` only after the requested result is implemented and verified.
|
|
7
|
+
- Leave concise comments for durable decisions, meaningful progress, blockers, verification results, and handoffs. Do not narrate every command or minor edit.
|
|
8
|
+
- Record a blocker relationship when another tracked task concretely prevents progress.
|
|
9
|
+
- Use ToDoddle timers only when the user requests time tracking or this repository explicitly requires it. Never invent recorded time.
|
|
10
|
+
- Archive tasks or time entries only with explicit user approval.
|
|
11
|
+
- If MCP access, scopes, or project grants are missing, report the exact limitation and list any tracking updates that remain pending. Never claim an update succeeded when it did not.
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tododdle-mcp",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Agent-first task, project context, and time tracking for ToDoddle",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"tododdle-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
".codex-plugin",
|
|
15
|
+
"skills",
|
|
16
|
+
"examples"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"start": "node dist/index.js",
|
|
21
|
+
"dev": "tsx src/index.ts",
|
|
22
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
23
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
24
|
+
"type-check": "tsc --noEmit",
|
|
25
|
+
"test": "npm run build && node --test test/*.test.mjs",
|
|
26
|
+
"prepack": "npm run build",
|
|
27
|
+
"prepublishOnly": "npm test"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"mcp",
|
|
31
|
+
"model-context-protocol",
|
|
32
|
+
"tododdle",
|
|
33
|
+
"project-management"
|
|
34
|
+
],
|
|
35
|
+
"author": "ToDoddle",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/krffl/tododdle-mcp.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://tododdle.com",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/krffl/tododdle-mcp/issues"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"provenance": true
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
51
|
+
"zod": "^3.24.1"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^22.15.0",
|
|
55
|
+
"prettier": "^3.3.3",
|
|
56
|
+
"tsx": "^4.23.1",
|
|
57
|
+
"typescript": "^7.0.2"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=18.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tododdle-workflow
|
|
3
|
+
description: Use ToDoddle as the work ledger for project planning, implementation, status updates, blockers, comments, and time tracking. Trigger when the user asks to inspect, plan, start, update, complete, or report on work managed in ToDoddle, or when repository instructions require ToDoddle updates. Do not trigger for casual discussion that does not change or review tracked work.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ToDoddle Workflow
|
|
7
|
+
|
|
8
|
+
Use the `tododdle` MCP tools for live project state. Never infer IDs, statuses, scopes, or relationships from memory.
|
|
9
|
+
|
|
10
|
+
## Start With Context
|
|
11
|
+
|
|
12
|
+
1. Use `list_projects` when the project is not already unambiguous.
|
|
13
|
+
2. Read `get_project_brief` and `get_project_context` before planning substantial work.
|
|
14
|
+
3. Use `get_work_queue`, `get_task`, and artifact tools to find existing work and supporting decisions.
|
|
15
|
+
4. Reuse an existing task when it covers the request. Create a task only when the work is genuinely untracked.
|
|
16
|
+
|
|
17
|
+
Keep list requests bounded and paginate rather than requesting an entire organization history.
|
|
18
|
+
|
|
19
|
+
## Manage Execution
|
|
20
|
+
|
|
21
|
+
- Transition the relevant task to the active status when substantive work begins.
|
|
22
|
+
- Keep task kind, parent, section, assignee, due date, priority, and blocker relationships accurate when the work changes them.
|
|
23
|
+
- Add comments only for durable information: decisions, meaningful progress, validation results, blockers, or handoff context.
|
|
24
|
+
- When blocked, set the blocker relationship when a concrete blocking task exists and explain the impact in one concise comment.
|
|
25
|
+
- Read Agent Connection replies with `get_agent_inbox` when continuing prior agent work; acknowledge a reply only after handling it.
|
|
26
|
+
|
|
27
|
+
Do not create bookkeeping churn for tiny exploratory actions. Prefer one useful checkpoint over a stream of narration.
|
|
28
|
+
|
|
29
|
+
## Finish Work
|
|
30
|
+
|
|
31
|
+
1. Run the verification appropriate to the work.
|
|
32
|
+
2. Add a concise final comment containing the outcome, notable decisions, and verification performed.
|
|
33
|
+
3. Transition the task to `COMPLETE` only when the requested outcome is actually achieved.
|
|
34
|
+
4. Leave incomplete work active and state what remains.
|
|
35
|
+
|
|
36
|
+
Use `archive_task` only when the user requests archival and approves the destructive action. Do not substitute archival for completion.
|
|
37
|
+
|
|
38
|
+
## Track Time
|
|
39
|
+
|
|
40
|
+
Use time tools when the user asks to track time or repository guidance makes time tracking expected:
|
|
41
|
+
|
|
42
|
+
- Check `get_active_time_entries` before starting a timer when duplicate timing would be confusing.
|
|
43
|
+
- Use `start_task_timer` and `stop_task_timer` for live work.
|
|
44
|
+
- Use `log_task_time` for known historical intervals.
|
|
45
|
+
- Correct entries with optimistic concurrency.
|
|
46
|
+
- Archive a time entry only with explicit approval.
|
|
47
|
+
|
|
48
|
+
Do not invent elapsed time or silently estimate it as recorded time.
|
|
49
|
+
|
|
50
|
+
## Handle Missing Access
|
|
51
|
+
|
|
52
|
+
If the MCP server is unavailable or a scope/project grant blocks an operation:
|
|
53
|
+
|
|
54
|
+
1. Report the missing server, scope, or grant precisely.
|
|
55
|
+
2. Do not fabricate a successful tracking update.
|
|
56
|
+
3. Continue non-destructive local work when reasonable, and clearly list the tracking updates still pending.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "ToDoddle Workflow"
|
|
3
|
+
short_description: "Run disciplined project workflows in ToDoddle"
|
|
4
|
+
default_prompt: "Use $tododdle-workflow to inspect project context and manage this work in ToDoddle."
|
|
5
|
+
|
|
6
|
+
dependencies:
|
|
7
|
+
tools:
|
|
8
|
+
- type: "mcp"
|
|
9
|
+
value: "tododdle"
|
|
10
|
+
description: "ToDoddle project, task, context, comment, and time tools"
|
|
11
|
+
transport: "stdio"
|
|
12
|
+
|
|
13
|
+
policy:
|
|
14
|
+
allow_implicit_invocation: true
|