frontier-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 +104 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +10 -0
- package/dist/bin.js.map +1 -0
- package/dist/domain.d.ts +230 -0
- package/dist/domain.d.ts.map +1 -0
- package/dist/domain.js +23 -0
- package/dist/domain.js.map +1 -0
- package/dist/edges.d.ts +35 -0
- package/dist/edges.d.ts.map +1 -0
- package/dist/edges.js +61 -0
- package/dist/edges.js.map +1 -0
- package/dist/frontier.d.ts +12 -0
- package/dist/frontier.d.ts.map +1 -0
- package/dist/frontier.js +34 -0
- package/dist/frontier.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +210 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/driver.d.ts +131 -0
- package/dist/storage/driver.d.ts.map +1 -0
- package/dist/storage/driver.js +43 -0
- package/dist/storage/driver.js.map +1 -0
- package/dist/storage/markdown/create.d.ts +52 -0
- package/dist/storage/markdown/create.d.ts.map +1 -0
- package/dist/storage/markdown/create.js +298 -0
- package/dist/storage/markdown/create.js.map +1 -0
- package/dist/storage/markdown/driver.d.ts +7 -0
- package/dist/storage/markdown/driver.d.ts.map +1 -0
- package/dist/storage/markdown/driver.js +492 -0
- package/dist/storage/markdown/driver.js.map +1 -0
- package/dist/storage/markdown/frontmatter.d.ts +17 -0
- package/dist/storage/markdown/frontmatter.d.ts.map +1 -0
- package/dist/storage/markdown/frontmatter.js +36 -0
- package/dist/storage/markdown/frontmatter.js.map +1 -0
- package/dist/storage/markdown/header-doc.d.ts +56 -0
- package/dist/storage/markdown/header-doc.d.ts.map +1 -0
- package/dist/storage/markdown/header-doc.js +287 -0
- package/dist/storage/markdown/header-doc.js.map +1 -0
- package/dist/storage/markdown/legacy.d.ts +16 -0
- package/dist/storage/markdown/legacy.d.ts.map +1 -0
- package/dist/storage/markdown/legacy.js +152 -0
- package/dist/storage/markdown/legacy.js.map +1 -0
- package/dist/storage/markdown/migrate.d.ts +27 -0
- package/dist/storage/markdown/migrate.d.ts.map +1 -0
- package/dist/storage/markdown/migrate.js +158 -0
- package/dist/storage/markdown/migrate.js.map +1 -0
- package/dist/storage/markdown/serialize.d.ts +37 -0
- package/dist/storage/markdown/serialize.d.ts.map +1 -0
- package/dist/storage/markdown/serialize.js +321 -0
- package/dist/storage/markdown/serialize.js.map +1 -0
- package/dist/storage/markdown/ticket.d.ts +12 -0
- package/dist/storage/markdown/ticket.d.ts.map +1 -0
- package/dist/storage/markdown/ticket.js +97 -0
- package/dist/storage/markdown/ticket.js.map +1 -0
- package/dist/storage/markdown/write.d.ts +42 -0
- package/dist/storage/markdown/write.d.ts.map +1 -0
- package/dist/storage/markdown/write.js +134 -0
- package/dist/storage/markdown/write.js.map +1 -0
- package/dist/tools/create-tickets.d.ts +63 -0
- package/dist/tools/create-tickets.d.ts.map +1 -0
- package/dist/tools/create-tickets.js +161 -0
- package/dist/tools/create-tickets.js.map +1 -0
- package/dist/tools/edit-map.d.ts +29 -0
- package/dist/tools/edit-map.d.ts.map +1 -0
- package/dist/tools/edit-map.js +81 -0
- package/dist/tools/edit-map.js.map +1 -0
- package/dist/tools/get-board.d.ts +29 -0
- package/dist/tools/get-board.d.ts.map +1 -0
- package/dist/tools/get-board.js +190 -0
- package/dist/tools/get-board.js.map +1 -0
- package/dist/tools/get-tickets.d.ts +14 -0
- package/dist/tools/get-tickets.d.ts.map +1 -0
- package/dist/tools/get-tickets.js +56 -0
- package/dist/tools/get-tickets.js.map +1 -0
- package/dist/tools/list-efforts.d.ts +16 -0
- package/dist/tools/list-efforts.d.ts.map +1 -0
- package/dist/tools/list-efforts.js +38 -0
- package/dist/tools/list-efforts.js.map +1 -0
- package/dist/tools/migrate-effort.d.ts +11 -0
- package/dist/tools/migrate-effort.d.ts.map +1 -0
- package/dist/tools/migrate-effort.js +54 -0
- package/dist/tools/migrate-effort.js.map +1 -0
- package/dist/tools/spec.d.ts +12 -0
- package/dist/tools/spec.d.ts.map +1 -0
- package/dist/tools/spec.js +27 -0
- package/dist/tools/spec.js.map +1 -0
- package/dist/tools/update-ticket.d.ts +62 -0
- package/dist/tools/update-ticket.d.ts.map +1 -0
- package/dist/tools/update-ticket.js +164 -0
- package/dist/tools/update-ticket.js.map +1 -0
- package/dist/tracker-doc.d.ts +10 -0
- package/dist/tracker-doc.d.ts.map +1 -0
- package/dist/tracker-doc.js +16 -0
- package/dist/tracker-doc.js.map +1 -0
- package/dist/workspace-index.d.ts +39 -0
- package/dist/workspace-index.d.ts.map +1 -0
- package/dist/workspace-index.js +83 -0
- package/dist/workspace-index.js.map +1 -0
- package/dist/workspace-watcher.d.ts +24 -0
- package/dist/workspace-watcher.d.ts.map +1 -0
- package/dist/workspace-watcher.js +87 -0
- package/dist/workspace-watcher.js.map +1 -0
- package/dist/workspace.d.ts +23 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +70 -0
- package/dist/workspace.js.map +1 -0
- package/docs/agents/issue-tracker.md +141 -0
- package/package.json +56 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Issue tracker — FrontierMCP and file fallback
|
|
2
|
+
|
|
3
|
+
Issues and specs live as markdown under `.scratch/`. Vocabulary is defined in the project's
|
|
4
|
+
`CONTEXT.md` when present — Effort, Board, Header doc, Map, Spec, Ticket, Edge, Frontier.
|
|
5
|
+
|
|
6
|
+
When **FrontierMCP** (server name `frontier`) is loaded in your session, use the tools below. They
|
|
7
|
+
own the schema, compute the graph, and answer orientation questions for a fraction of the token cost
|
|
8
|
+
of reading every Ticket file. When it is **not** loaded, follow the [File conventions](#file-conventions)
|
|
9
|
+
literally — the same files, the same fields, written by hand.
|
|
10
|
+
|
|
11
|
+
Read this document once at setup. In Cursor it is also available as MCP resource `frontier://tracker-doc`.
|
|
12
|
+
|
|
13
|
+
## Workspace
|
|
14
|
+
|
|
15
|
+
FrontierMCP resolves which repository it serves on every call:
|
|
16
|
+
|
|
17
|
+
1. An explicit `root` argument on the call.
|
|
18
|
+
2. The `FRONTIER_ROOT` environment variable.
|
|
19
|
+
3. The server process working directory, walked upward to the nearest directory containing `.scratch/`
|
|
20
|
+
or `.git/`.
|
|
21
|
+
|
|
22
|
+
Register FrontierMCP once at user scope. Opening a project is the only per-repo setup step — no
|
|
23
|
+
`.cursor/mcp.json` entry is required in each repository.
|
|
24
|
+
|
|
25
|
+
A repo with no `.scratch/` yet is not an error. Create an Effort by writing to it with `create: true`
|
|
26
|
+
on `create_tickets`, `edit_map`, or `spec`.
|
|
27
|
+
|
|
28
|
+
## MCP tools
|
|
29
|
+
|
|
30
|
+
Eight tools permanently. Optional arguments extend an existing tool; there is no ninth.
|
|
31
|
+
|
|
32
|
+
| Tool | Use when |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| `list_efforts` | Orient — list Efforts with Ticket counts, header doc kinds, and Frontier size. |
|
|
35
|
+
| `get_board` | See the whole Effort cheaply — Destination, one summary line per Ticket, Frontier marked. Never returns bodies. |
|
|
36
|
+
| `get_tickets` | Fetch full bodies for specific ids after the Board tells you which Tickets matter. |
|
|
37
|
+
| `create_tickets` | Publish a breakdown in one call. Declare Edges with temporary keys; the server assigns ids and numbers. |
|
|
38
|
+
| `update_ticket` | Claim, resolve, drop, set triage, replace Edges, comment, or tick acceptance criteria. One Ticket per call. |
|
|
39
|
+
| `edit_map` | Edit Map sections — Destination, Notes, fog, Out of scope. Decisions-so-far regenerates from resolved Tickets. |
|
|
40
|
+
| `spec` | Read or write a Spec as a whole document. |
|
|
41
|
+
| `migrate_effort` | Normalize Legacy Tickets in an Effort. Preview writes nothing; filename rename is opt-in. |
|
|
42
|
+
|
|
43
|
+
### Typical agent flow
|
|
44
|
+
|
|
45
|
+
1. `list_efforts` — pick an Effort.
|
|
46
|
+
2. `get_board` on that Effort — read the Frontier (`>` marker).
|
|
47
|
+
3. `get_tickets` on the ids you will work — read bodies only for those Tickets.
|
|
48
|
+
4. `update_ticket` with `claim` before starting work.
|
|
49
|
+
5. `update_ticket` with `resolve` or `drop` when done; tick criteria and comment as you go.
|
|
50
|
+
6. `create_tickets` when a skill publishes a new breakdown; `edit_map` / `spec` for header docs.
|
|
51
|
+
|
|
52
|
+
### Skill mapping
|
|
53
|
+
|
|
54
|
+
| Skill says | FrontierMCP call |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| publish to the issue tracker | `create_tickets` |
|
|
57
|
+
| fetch the relevant ticket | `get_tickets` |
|
|
58
|
+
| what can I work on / frontier | `get_board` |
|
|
59
|
+
| claim before work | `update_ticket` with `claim` |
|
|
60
|
+
| resolve with an answer | `update_ticket` with `resolve` |
|
|
61
|
+
| rule out of scope | `update_ticket` with `drop`, then `edit_map` `rule_out` if needed |
|
|
62
|
+
| edit the Map | `edit_map` |
|
|
63
|
+
| write or read the Spec | `spec` |
|
|
64
|
+
| normalize legacy files | `migrate_effort` |
|
|
65
|
+
|
|
66
|
+
Claims are compare-and-set — a parallel session that already holds the Ticket wins. Writes carry the
|
|
67
|
+
`revision` from the last read; a mismatch is refused, never retried over the caller's edit.
|
|
68
|
+
|
|
69
|
+
## File conventions
|
|
70
|
+
|
|
71
|
+
These conventions are canonical whether FrontierMCP is loaded or not. FrontierMCP reads and writes the same
|
|
72
|
+
files; a session without the server still produces valid Tickets by following this section.
|
|
73
|
+
|
|
74
|
+
### Layout
|
|
75
|
+
|
|
76
|
+
- One Effort per directory: `.scratch/<effort-slug>/`
|
|
77
|
+
- The header doc is `spec.md` (from `/to-spec`) or `map.md` (from `/wayfinder`). An Effort charted as a
|
|
78
|
+
Map may later gain a Spec — that is wayfinder's handoff, not a mistake.
|
|
79
|
+
- Tickets are one file per Ticket under `.scratch/<effort-slug>/issues/` — never a single combined
|
|
80
|
+
tickets file.
|
|
81
|
+
- Ticket filenames are `<NN>-T<n>-<slug>.md`. `NN` is sort order only and may be rewritten. `T<n>` is
|
|
82
|
+
the identity and never changes.
|
|
83
|
+
- **Ticket ids are `T<n>`, unique across the whole repo.** Before creating one by hand, scan every
|
|
84
|
+
`.scratch/*/issues/` for the highest existing `T` number and continue from there — ids do not restart
|
|
85
|
+
per Effort. A bare `T47` therefore resolves anywhere in the repo, including in commit messages.
|
|
86
|
+
- Formal metadata goes in YAML frontmatter. Prose stays prose.
|
|
87
|
+
|
|
88
|
+
### Ticket frontmatter
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
---
|
|
92
|
+
id: T12 # T<n>, repo-unique, never reused
|
|
93
|
+
title: Parse legacy tickets without frontmatter
|
|
94
|
+
kind: build # build | decision
|
|
95
|
+
type: research # decision only: research | prototype | grilling | task
|
|
96
|
+
status: open # open | claimed | resolved | dropped
|
|
97
|
+
triage: ready-for-agent # see triage-labels.md
|
|
98
|
+
blocked_by: [T09, T11] # plain ids, resolved repo-wide
|
|
99
|
+
claimed_by: # required when status: claimed
|
|
100
|
+
claimed_at: # timestamp, set with claimed_by
|
|
101
|
+
answer_gist: # required when status: resolved — one line, every kind
|
|
102
|
+
dropped_reason: # required when status: dropped
|
|
103
|
+
---
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Body shape follows whichever skill produced the Ticket: Problem / Done when / acceptance criteria for
|
|
107
|
+
`build`, `## Question` / `## Acceptance criteria` / `## Answer` for `decision`. Comments append at the
|
|
108
|
+
bottom under `## Comments`.
|
|
109
|
+
|
|
110
|
+
### Status
|
|
111
|
+
|
|
112
|
+
`open` → `claimed` → `resolved` or `dropped`. Both terminal states are closed and differ in meaning:
|
|
113
|
+
`resolved` is a step on the route and contributes its `answer_gist` to the Map's Decisions-so-far;
|
|
114
|
+
`dropped` is work ruled beyond the destination and contributes its `dropped_reason` to Out of scope.
|
|
115
|
+
`wontfix` is a triage role, not a status.
|
|
116
|
+
|
|
117
|
+
A dropped Ticket does **not** unblock its dependents — flag them for a human instead.
|
|
118
|
+
|
|
119
|
+
### Map operations (wayfinder)
|
|
120
|
+
|
|
121
|
+
Used by `/wayfinder`. The **Map** is a file with one **child** file per Ticket.
|
|
122
|
+
|
|
123
|
+
- **Map**: `.scratch/<effort-slug>/map.md` — Destination, Notes, Decisions so far, Not yet specified,
|
|
124
|
+
Out of scope.
|
|
125
|
+
- **Child ticket**: a file under `issues/` with the question in the body, `kind: decision`, and a
|
|
126
|
+
`type:` recording which wayfinder type it is.
|
|
127
|
+
- **Blocking**: the `blocked_by` list. A Ticket is unblocked when every id it lists is `resolved`.
|
|
128
|
+
- **Frontier**: Tickets that are `open`, unblocked, and unclaimed; lowest `NN` first.
|
|
129
|
+
- **Claim**: set `status: claimed` with `claimed_by` and `claimed_at`, and save, before any work.
|
|
130
|
+
- **Resolve**: append the answer under `## Answer`, set `status: resolved` and a one-line
|
|
131
|
+
`answer_gist`, then add the pointer line to the Map's Decisions-so-far.
|
|
132
|
+
- **Rule out of scope**: set `status: dropped` with a `dropped_reason`, and add the line to the Map's
|
|
133
|
+
Out of scope. Do not put it in Decisions-so-far — that section records the route actually walked.
|
|
134
|
+
|
|
135
|
+
When FrontierMCP is loaded, prefer the MCP calls in the table above over hand-editing these fields.
|
|
136
|
+
|
|
137
|
+
### Hand publish (no FrontierMCP)
|
|
138
|
+
|
|
139
|
+
When a skill says "publish to the issue tracker" and FrontierMCP is not loaded, create
|
|
140
|
+
`.scratch/<effort-slug>/issues/<NN>-T<n>-<slug>.md` (creating directories as needed), assign the next
|
|
141
|
+
repo-global `T<n>`, and write frontmatter matching the template above.
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "frontier-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "An MCP server exposing the markdown issue tracker under a repo's .scratch/ as a queryable graph",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/51ck/frontier-mcp.git"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"frontier-mcp": "./dist/bin.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"docs/agents/issue-tracker.md"
|
|
16
|
+
],
|
|
17
|
+
"type": "module",
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"default": "./dist/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
28
|
+
"yaml": "^2.9.0",
|
|
29
|
+
"zod": "^4.4.3"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@release-it/conventional-changelog": "^12.0.0",
|
|
33
|
+
"@types/node": "^24.10.1",
|
|
34
|
+
"oxfmt": "^0.62.0",
|
|
35
|
+
"oxlint": "^1.77.0",
|
|
36
|
+
"release-it": "^21.0.1",
|
|
37
|
+
"typescript": "^7.0.2",
|
|
38
|
+
"vitest": "^4.1.10"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=24"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc",
|
|
45
|
+
"typecheck": "tsc -p tsconfig.test.json",
|
|
46
|
+
"lint": "oxlint",
|
|
47
|
+
"lint:fix": "oxlint --fix",
|
|
48
|
+
"format": "oxfmt --write",
|
|
49
|
+
"format:check": "oxfmt --check",
|
|
50
|
+
"check": "pnpm run typecheck && pnpm run lint && pnpm run format:check",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"start": "node src/bin.ts",
|
|
54
|
+
"release:dry": "release-it --dry-run --ci"
|
|
55
|
+
}
|
|
56
|
+
}
|