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.
Files changed (115) hide show
  1. package/README.md +104 -0
  2. package/dist/bin.d.ts +3 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +10 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/domain.d.ts +230 -0
  7. package/dist/domain.d.ts.map +1 -0
  8. package/dist/domain.js +23 -0
  9. package/dist/domain.js.map +1 -0
  10. package/dist/edges.d.ts +35 -0
  11. package/dist/edges.d.ts.map +1 -0
  12. package/dist/edges.js +61 -0
  13. package/dist/edges.js.map +1 -0
  14. package/dist/frontier.d.ts +12 -0
  15. package/dist/frontier.d.ts.map +1 -0
  16. package/dist/frontier.js +34 -0
  17. package/dist/frontier.js.map +1 -0
  18. package/dist/index.d.ts +5 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/server.d.ts +29 -0
  23. package/dist/server.d.ts.map +1 -0
  24. package/dist/server.js +210 -0
  25. package/dist/server.js.map +1 -0
  26. package/dist/storage/driver.d.ts +131 -0
  27. package/dist/storage/driver.d.ts.map +1 -0
  28. package/dist/storage/driver.js +43 -0
  29. package/dist/storage/driver.js.map +1 -0
  30. package/dist/storage/markdown/create.d.ts +52 -0
  31. package/dist/storage/markdown/create.d.ts.map +1 -0
  32. package/dist/storage/markdown/create.js +298 -0
  33. package/dist/storage/markdown/create.js.map +1 -0
  34. package/dist/storage/markdown/driver.d.ts +7 -0
  35. package/dist/storage/markdown/driver.d.ts.map +1 -0
  36. package/dist/storage/markdown/driver.js +492 -0
  37. package/dist/storage/markdown/driver.js.map +1 -0
  38. package/dist/storage/markdown/frontmatter.d.ts +17 -0
  39. package/dist/storage/markdown/frontmatter.d.ts.map +1 -0
  40. package/dist/storage/markdown/frontmatter.js +36 -0
  41. package/dist/storage/markdown/frontmatter.js.map +1 -0
  42. package/dist/storage/markdown/header-doc.d.ts +56 -0
  43. package/dist/storage/markdown/header-doc.d.ts.map +1 -0
  44. package/dist/storage/markdown/header-doc.js +287 -0
  45. package/dist/storage/markdown/header-doc.js.map +1 -0
  46. package/dist/storage/markdown/legacy.d.ts +16 -0
  47. package/dist/storage/markdown/legacy.d.ts.map +1 -0
  48. package/dist/storage/markdown/legacy.js +152 -0
  49. package/dist/storage/markdown/legacy.js.map +1 -0
  50. package/dist/storage/markdown/migrate.d.ts +27 -0
  51. package/dist/storage/markdown/migrate.d.ts.map +1 -0
  52. package/dist/storage/markdown/migrate.js +158 -0
  53. package/dist/storage/markdown/migrate.js.map +1 -0
  54. package/dist/storage/markdown/serialize.d.ts +37 -0
  55. package/dist/storage/markdown/serialize.d.ts.map +1 -0
  56. package/dist/storage/markdown/serialize.js +321 -0
  57. package/dist/storage/markdown/serialize.js.map +1 -0
  58. package/dist/storage/markdown/ticket.d.ts +12 -0
  59. package/dist/storage/markdown/ticket.d.ts.map +1 -0
  60. package/dist/storage/markdown/ticket.js +97 -0
  61. package/dist/storage/markdown/ticket.js.map +1 -0
  62. package/dist/storage/markdown/write.d.ts +42 -0
  63. package/dist/storage/markdown/write.d.ts.map +1 -0
  64. package/dist/storage/markdown/write.js +134 -0
  65. package/dist/storage/markdown/write.js.map +1 -0
  66. package/dist/tools/create-tickets.d.ts +63 -0
  67. package/dist/tools/create-tickets.d.ts.map +1 -0
  68. package/dist/tools/create-tickets.js +161 -0
  69. package/dist/tools/create-tickets.js.map +1 -0
  70. package/dist/tools/edit-map.d.ts +29 -0
  71. package/dist/tools/edit-map.d.ts.map +1 -0
  72. package/dist/tools/edit-map.js +81 -0
  73. package/dist/tools/edit-map.js.map +1 -0
  74. package/dist/tools/get-board.d.ts +29 -0
  75. package/dist/tools/get-board.d.ts.map +1 -0
  76. package/dist/tools/get-board.js +190 -0
  77. package/dist/tools/get-board.js.map +1 -0
  78. package/dist/tools/get-tickets.d.ts +14 -0
  79. package/dist/tools/get-tickets.d.ts.map +1 -0
  80. package/dist/tools/get-tickets.js +56 -0
  81. package/dist/tools/get-tickets.js.map +1 -0
  82. package/dist/tools/list-efforts.d.ts +16 -0
  83. package/dist/tools/list-efforts.d.ts.map +1 -0
  84. package/dist/tools/list-efforts.js +38 -0
  85. package/dist/tools/list-efforts.js.map +1 -0
  86. package/dist/tools/migrate-effort.d.ts +11 -0
  87. package/dist/tools/migrate-effort.d.ts.map +1 -0
  88. package/dist/tools/migrate-effort.js +54 -0
  89. package/dist/tools/migrate-effort.js.map +1 -0
  90. package/dist/tools/spec.d.ts +12 -0
  91. package/dist/tools/spec.d.ts.map +1 -0
  92. package/dist/tools/spec.js +27 -0
  93. package/dist/tools/spec.js.map +1 -0
  94. package/dist/tools/update-ticket.d.ts +62 -0
  95. package/dist/tools/update-ticket.d.ts.map +1 -0
  96. package/dist/tools/update-ticket.js +164 -0
  97. package/dist/tools/update-ticket.js.map +1 -0
  98. package/dist/tracker-doc.d.ts +10 -0
  99. package/dist/tracker-doc.d.ts.map +1 -0
  100. package/dist/tracker-doc.js +16 -0
  101. package/dist/tracker-doc.js.map +1 -0
  102. package/dist/workspace-index.d.ts +39 -0
  103. package/dist/workspace-index.d.ts.map +1 -0
  104. package/dist/workspace-index.js +83 -0
  105. package/dist/workspace-index.js.map +1 -0
  106. package/dist/workspace-watcher.d.ts +24 -0
  107. package/dist/workspace-watcher.d.ts.map +1 -0
  108. package/dist/workspace-watcher.js +87 -0
  109. package/dist/workspace-watcher.js.map +1 -0
  110. package/dist/workspace.d.ts +23 -0
  111. package/dist/workspace.d.ts.map +1 -0
  112. package/dist/workspace.js +70 -0
  113. package/dist/workspace.js.map +1 -0
  114. package/docs/agents/issue-tracker.md +141 -0
  115. 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
+ }