@hanna84/mcp-writing 1.7.0 → 1.8.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/CHANGELOG.md +10 -0
- package/README.md +1 -1
- package/db.js +32 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/sync.js +18 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,21 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v1.8.0](https://github.com/hannasdev/mcp-writing.git
|
|
8
|
+
/compare/v1.7.0...v1.8.0)
|
|
9
|
+
|
|
10
|
+
- feat(search): index metadata keywords in scenes FTS and preserve legacy index data [`#50`](https://github.com/hannasdev/mcp-writing.git
|
|
11
|
+
/pull/50)
|
|
12
|
+
|
|
7
13
|
#### [v1.7.0](https://github.com/hannasdev/mcp-writing.git
|
|
8
14
|
/compare/v1.6.3...v1.7.0)
|
|
9
15
|
|
|
16
|
+
> 19 April 2026
|
|
17
|
+
|
|
10
18
|
- feat: configurable OpenClaw runtime identity and ownership guardrails [`#49`](https://github.com/hannasdev/mcp-writing.git
|
|
11
19
|
/pull/49)
|
|
20
|
+
- Release 1.7.0 [`f859eb5`](https://github.com/hannasdev/mcp-writing.git
|
|
21
|
+
/commit/f859eb57bcea412591635185e113f2c6467b0f59)
|
|
12
22
|
|
|
13
23
|
#### [v1.6.3](https://github.com/hannasdev/mcp-writing.git
|
|
14
24
|
/compare/v1.6.2...v1.6.3)
|
package/README.md
CHANGED
|
@@ -315,7 +315,7 @@ Outcome: you get AI speed with explicit approval and recoverable history for eve
|
|
|
315
315
|
| `list_places` | All places |
|
|
316
316
|
| `get_place_sheet` | Full place metadata, tags, associated characters, notes, and support notes |
|
|
317
317
|
| `create_place_sheet` | Create a canonical place sheet folder and sidecar |
|
|
318
|
-
| `search_metadata` | Full-text search across scene titles and
|
|
318
|
+
| `search_metadata` | Full-text search across scene titles, loglines, and metadata keywords (tags/characters/places/versions) |
|
|
319
319
|
| `list_threads` | All subplot threads for a project |
|
|
320
320
|
| `get_thread_arc` | Scenes belonging to a thread, with per-thread beat |
|
|
321
321
|
| `upsert_thread_link` | Create/update a thread and link it to a scene |
|
package/db.js
CHANGED
|
@@ -116,12 +116,43 @@ export const SCHEMA = `
|
|
|
116
116
|
);
|
|
117
117
|
|
|
118
118
|
CREATE VIRTUAL TABLE IF NOT EXISTS scenes_fts USING fts5(
|
|
119
|
-
scene_id, project_id, logline, title
|
|
119
|
+
scene_id, project_id, logline, title, keywords
|
|
120
120
|
);
|
|
121
121
|
`;
|
|
122
122
|
|
|
123
123
|
export function openDb(dbPath) {
|
|
124
124
|
const db = new DatabaseSync(dbPath);
|
|
125
125
|
db.exec(SCHEMA);
|
|
126
|
+
|
|
127
|
+
// Rebuild legacy FTS table if it predates keyword indexing.
|
|
128
|
+
// Preserve existing indexed rows so metadata search remains available
|
|
129
|
+
// even before the next sync pass repopulates from source files.
|
|
130
|
+
const ftsSql = db.prepare(`
|
|
131
|
+
SELECT sql
|
|
132
|
+
FROM sqlite_master
|
|
133
|
+
WHERE type = 'table' AND name = 'scenes_fts'
|
|
134
|
+
`).get()?.sql;
|
|
135
|
+
if (typeof ftsSql === "string" && !ftsSql.toLowerCase().includes("keywords")) {
|
|
136
|
+
db.exec(`BEGIN IMMEDIATE;`);
|
|
137
|
+
try {
|
|
138
|
+
db.exec(`
|
|
139
|
+
CREATE VIRTUAL TABLE scenes_fts_migrating USING fts5(
|
|
140
|
+
scene_id, project_id, logline, title, keywords
|
|
141
|
+
);
|
|
142
|
+
`);
|
|
143
|
+
db.exec(`
|
|
144
|
+
INSERT INTO scenes_fts_migrating (scene_id, project_id, logline, title, keywords)
|
|
145
|
+
SELECT scene_id, project_id, logline, title, ''
|
|
146
|
+
FROM scenes_fts;
|
|
147
|
+
`);
|
|
148
|
+
db.exec(`DROP TABLE scenes_fts;`);
|
|
149
|
+
db.exec(`ALTER TABLE scenes_fts_migrating RENAME TO scenes_fts;`);
|
|
150
|
+
db.exec(`COMMIT;`);
|
|
151
|
+
} catch (err) {
|
|
152
|
+
db.exec(`ROLLBACK;`);
|
|
153
|
+
throw err;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
126
157
|
return db;
|
|
127
158
|
}
|
package/index.js
CHANGED
|
@@ -946,7 +946,7 @@ function createMcpServer() {
|
|
|
946
946
|
// ---- search_metadata -----------------------------------------------------
|
|
947
947
|
s.tool(
|
|
948
948
|
"search_metadata",
|
|
949
|
-
"Full-text search across scene titles
|
|
949
|
+
"Full-text search across scene titles, loglines (synopsis/logline text fields), and metadata keywords (tags/characters/places/versions). Use this when you don't know the exact scene_id or chapter but want to find scenes by topic, theme, or metadata keyword. Not a prose search — use get_scene_prose to read actual text. Supports pagination via page/page_size and auto-paginates large result sets with total_count.",
|
|
950
950
|
{
|
|
951
951
|
query: z.string().describe("Search terms (e.g. 'hospital' or 'Sebastian feeding'). FTS5 syntax supported."),
|
|
952
952
|
page: z.number().int().min(1).optional().describe("Optional page number for paginated responses (1-based)."),
|
package/package.json
CHANGED
package/sync.js
CHANGED
|
@@ -515,8 +515,24 @@ export function indexSceneFile(db, syncDir, file, meta, prose) {
|
|
|
515
515
|
);
|
|
516
516
|
}
|
|
517
517
|
|
|
518
|
-
|
|
519
|
-
meta.
|
|
518
|
+
const keywordTokens = [
|
|
519
|
+
...(meta.tags ?? []),
|
|
520
|
+
...(meta.characters ?? []),
|
|
521
|
+
...(meta.places ?? []),
|
|
522
|
+
...(meta.versions ?? []),
|
|
523
|
+
]
|
|
524
|
+
.filter(Boolean)
|
|
525
|
+
.map(String)
|
|
526
|
+
.map(s => s.trim())
|
|
527
|
+
.filter(Boolean)
|
|
528
|
+
.join(" ");
|
|
529
|
+
|
|
530
|
+
db.prepare(`INSERT OR REPLACE INTO scenes_fts (scene_id, project_id, logline, title, keywords) VALUES (?, ?, ?, ?, ?)`).run(
|
|
531
|
+
meta.scene_id,
|
|
532
|
+
project_id,
|
|
533
|
+
meta.logline ?? meta.synopsis ?? "",
|
|
534
|
+
meta.title ?? "",
|
|
535
|
+
keywordTokens,
|
|
520
536
|
);
|
|
521
537
|
|
|
522
538
|
return { isStale };
|