@kezlahd/atlas-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 +77 -0
- package/dist/api.js +70 -0
- package/dist/api.js.map +1 -0
- package/dist/index.js +685 -0
- package/dist/index.js.map +1 -0
- package/dist/section-catalog.js +131 -0
- package/dist/section-catalog.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# @kezlahd/atlas-mcp
|
|
2
|
+
|
|
3
|
+
MCP server that lets Claude Code (and other MCP-aware AI agents) edit Atlas doc templates, files, and gear directly. Sibling of `@kezlahd/atlas-cli` – same auth (Bearer token), same endpoints, same optimistic-concurrency safety (get-then-put with etag).
|
|
4
|
+
|
|
5
|
+
## Setup in Claude Code
|
|
6
|
+
|
|
7
|
+
1. Mint a token: [Atlas](https://atlas.mjsons.net) → workspace → Settings → API keys → Mint token. Copy the plaintext.
|
|
8
|
+
2. Add the server to your Claude Code MCP config (usually `~/.claude/config.json` or `claude_desktop_config.json`):
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"mcpServers": {
|
|
13
|
+
"atlas": {
|
|
14
|
+
"command": "npx",
|
|
15
|
+
"args": ["-y", "@kezlahd/atlas-mcp"],
|
|
16
|
+
"env": {
|
|
17
|
+
"ATLAS_TOKEN": "atlas_pat_…",
|
|
18
|
+
"ATLAS_WORKSPACE": "acme-inc"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
3. Restart Claude Code. You should see the `atlas` server connect on stderr.
|
|
26
|
+
|
|
27
|
+
For dev – run out of the workspace instead:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"mcpServers": {
|
|
32
|
+
"atlas": {
|
|
33
|
+
"command": "pnpm",
|
|
34
|
+
"args": ["--filter", "@kezlahd/atlas-mcp", "dev"],
|
|
35
|
+
"cwd": "/path/to/the-studio",
|
|
36
|
+
"env": {
|
|
37
|
+
"ATLAS_TOKEN": "atlas_pat_…",
|
|
38
|
+
"ATLAS_WORKSPACE": "acme-inc"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Tools exposed
|
|
46
|
+
|
|
47
|
+
| Tool | Purpose | Scope |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| `atlas_list_docs` | List docs in the workspace | `templates:list` |
|
|
50
|
+
| `atlas_get_template` | Fetch full template content (returns etag) | `templates:get` |
|
|
51
|
+
| `atlas_list_sections` | Summarise section ids + types + titles (cheap) | `templates:get` |
|
|
52
|
+
| `atlas_describe_section_type` | Look up what fields a section type takes | none |
|
|
53
|
+
| `atlas_update_section` | Edit one section by id – safe, scoped, auto-etag | `templates:update` |
|
|
54
|
+
| `atlas_update_template` | Replace the whole template – for restructuring | `templates:update` |
|
|
55
|
+
| `atlas_list_revisions` | List revision history for a template | `templates:list-revisions` |
|
|
56
|
+
| `atlas_restore_revision` | Restore a template to an earlier revision | `templates:restore-revision` |
|
|
57
|
+
| `atlas_list_files` | List workspace files with signed URLs | `files:list` |
|
|
58
|
+
| `atlas_get_file_url` | Fetch a signed URL for a single file | `files:list` |
|
|
59
|
+
| `atlas_upload_file` | Upload a local file to workspace storage | `files:upload` |
|
|
60
|
+
| `atlas_rename_file` | Rename a workspace file | `files:rename` |
|
|
61
|
+
| `atlas_set_file_alt` | Update the alt-text metadata for a file | `files:edit-alt` |
|
|
62
|
+
| `atlas_delete_file` | Delete a workspace file | `files:delete` |
|
|
63
|
+
| `atlas_list_gear` | List gear items in the workspace | `gear:list` |
|
|
64
|
+
| `atlas_add_gear` | Add a new gear item | `gear:add` |
|
|
65
|
+
| `atlas_update_gear` | Patch an existing gear item | `gear:update` |
|
|
66
|
+
| `atlas_delete_gear` | Delete a gear item | `gear:delete` |
|
|
67
|
+
| `atlas_import_gear` | Bulk import gear from CSV | `gear:import` |
|
|
68
|
+
|
|
69
|
+
Every template write is journaled to `doc_template_revisions` server-side, so any bad push from a chat can be reverted from the UI.
|
|
70
|
+
|
|
71
|
+
## The pattern to teach Claude
|
|
72
|
+
|
|
73
|
+
> Pull `atlas_list_sections` first (cheap), then `atlas_describe_section_type` for the section you're editing, then `atlas_update_section` with the correct shape. Only reach for `atlas_update_template` when you're restructuring the doc.
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
MIT
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client shared by every MCP tool. Same shape as the CLI's api.ts —
|
|
3
|
+
* couldn't reuse it directly because the CLI reads config from disk +
|
|
4
|
+
* env; MCP reads from env only (Claude Code's MCP config passes ATLAS_*).
|
|
5
|
+
*/
|
|
6
|
+
const DEFAULT_API_URL = "https://atlas.mjsons.net";
|
|
7
|
+
export function resolveConfig() {
|
|
8
|
+
const token = process.env.ATLAS_TOKEN;
|
|
9
|
+
const workspace = process.env.ATLAS_WORKSPACE;
|
|
10
|
+
const apiUrl = (process.env.ATLAS_API_URL ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
11
|
+
if (!token) {
|
|
12
|
+
throw new Error("ATLAS_TOKEN env var is required. Add it to your MCP server config in Claude Code (see the atlas-mcp README).");
|
|
13
|
+
}
|
|
14
|
+
if (!workspace) {
|
|
15
|
+
throw new Error("ATLAS_WORKSPACE env var is required (workspace slug — lowercase alnum + dashes).");
|
|
16
|
+
}
|
|
17
|
+
return { apiUrl, token, workspace };
|
|
18
|
+
}
|
|
19
|
+
export class ApiError extends Error {
|
|
20
|
+
status;
|
|
21
|
+
body;
|
|
22
|
+
constructor(status, body, message) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.status = status;
|
|
25
|
+
this.body = body;
|
|
26
|
+
this.name = "ApiError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export async function apiRequest(cfg, path, opts = {}) {
|
|
30
|
+
const url = new URL(path, cfg.apiUrl);
|
|
31
|
+
if (opts.query) {
|
|
32
|
+
for (const [k, v] of Object.entries(opts.query)) {
|
|
33
|
+
if (v !== undefined)
|
|
34
|
+
url.searchParams.set(k, String(v));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const headers = {
|
|
38
|
+
Authorization: `Bearer ${cfg.token}`,
|
|
39
|
+
Accept: "application/json",
|
|
40
|
+
};
|
|
41
|
+
if (opts.body !== undefined)
|
|
42
|
+
headers["Content-Type"] = "application/json";
|
|
43
|
+
if (opts.ifMatch)
|
|
44
|
+
headers["If-Match"] = opts.ifMatch;
|
|
45
|
+
const res = await fetch(url, {
|
|
46
|
+
method: opts.method ?? "GET",
|
|
47
|
+
headers,
|
|
48
|
+
body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
|
|
49
|
+
});
|
|
50
|
+
const text = await res.text();
|
|
51
|
+
const body = text ? safeJson(text) : null;
|
|
52
|
+
if (!res.ok) {
|
|
53
|
+
const message = (isRecord(body) && typeof body.error === "string" && body.error) ||
|
|
54
|
+
`HTTP ${res.status}`;
|
|
55
|
+
throw new ApiError(res.status, body, message);
|
|
56
|
+
}
|
|
57
|
+
return { data: body, etag: res.headers.get("etag") };
|
|
58
|
+
}
|
|
59
|
+
function safeJson(text) {
|
|
60
|
+
try {
|
|
61
|
+
return JSON.parse(text);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return text;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function isRecord(v) {
|
|
68
|
+
return typeof v === "object" && v !== null;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Atlas MCP server.
|
|
4
|
+
*
|
|
5
|
+
* Exposes doc-template read/write tools to Claude Code (or any MCP client)
|
|
6
|
+
* via stdio. Uses the exact same /api/v1 endpoints the CLI + web settings
|
|
7
|
+
* page use — one source of truth for auth, rate limiting, revisions.
|
|
8
|
+
*
|
|
9
|
+
* Config: env only (Claude Code's MCP config passes these as `env`):
|
|
10
|
+
* ATLAS_TOKEN — Bearer token from workspace → Settings → API keys
|
|
11
|
+
* ATLAS_WORKSPACE — workspace slug
|
|
12
|
+
* ATLAS_API_URL — optional override, default https://atlas.mjsons.net
|
|
13
|
+
*
|
|
14
|
+
* All writes use get-then-put with the fresh etag, so a concurrent
|
|
15
|
+
* autosave from the web editor can't be silently overwritten — a 409
|
|
16
|
+
* bubbles up to Claude as a tool error and the model can re-fetch.
|
|
17
|
+
*/
|
|
18
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
19
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
20
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
import { apiRequest, ApiError, resolveConfig } from "./api.js";
|
|
22
|
+
import { SECTION_CATALOG, findSection } from "./section-catalog.js";
|
|
23
|
+
/* ─── Tool definitions ─────────────────────────────────────────────── */
|
|
24
|
+
const TOOLS = [
|
|
25
|
+
{
|
|
26
|
+
name: "atlas_list_docs",
|
|
27
|
+
description: "List docs in the current Atlas workspace. Returns { docs, next_cursor }. Use this to find a docId before pulling a template. To page through more, pass the previous next_cursor back in as `cursor`.",
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
kind: {
|
|
32
|
+
type: "string",
|
|
33
|
+
enum: ["template", "freeform"],
|
|
34
|
+
description: "Optional filter — templates are the doc-crafter kind.",
|
|
35
|
+
},
|
|
36
|
+
limit: { type: "number", description: "Max results (default 50, max 500)." },
|
|
37
|
+
cursor: {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "Opaque next_cursor from a previous response. Omit for the first page.",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "atlas_get_template",
|
|
46
|
+
description: "Fetch a doc template's full content (cover + sections). Returns { id, title, template_content, etag }. Use this before editing so you can pass sections to atlas_update_section.",
|
|
47
|
+
inputSchema: {
|
|
48
|
+
type: "object",
|
|
49
|
+
properties: {
|
|
50
|
+
docId: { type: "string", description: "Doc id from atlas_list_docs." },
|
|
51
|
+
},
|
|
52
|
+
required: ["docId"],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "atlas_list_sections",
|
|
57
|
+
description: "Summarise the sections in a doc without pulling the full data payloads. Returns [{ id, type, title }]. Cheaper than atlas_get_template when you only need to know what's in the doc.",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
docId: { type: "string" },
|
|
62
|
+
},
|
|
63
|
+
required: ["docId"],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "atlas_update_section",
|
|
68
|
+
description: "Edit a single section by id. Fetches current template, splices in the new section.data (and optionally style), writes back with the fresh etag. Safer than atlas_update_template for scoped edits — won't touch other sections.",
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: "object",
|
|
71
|
+
properties: {
|
|
72
|
+
docId: { type: "string" },
|
|
73
|
+
sectionId: { type: "string", description: "Section id to update." },
|
|
74
|
+
data: {
|
|
75
|
+
type: "object",
|
|
76
|
+
description: "New section.data payload — replaces the existing data object entirely. Use atlas_describe_section_type first to learn the shape.",
|
|
77
|
+
},
|
|
78
|
+
style: {
|
|
79
|
+
type: "object",
|
|
80
|
+
description: "Optional section.style overrides (titleFont, titleSize, breakBefore, etc). Merged into existing style.",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
required: ["docId", "sectionId", "data"],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "atlas_update_template",
|
|
88
|
+
description: "Replace a doc's full template_content (cover + sections). Use this for large restructuring — reordering sections, replacing the cover, batch edits. For a single-section change, prefer atlas_update_section. Uses get-then-put with etag so it won't silently overwrite concurrent web edits.",
|
|
89
|
+
inputSchema: {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
docId: { type: "string" },
|
|
93
|
+
template_content: {
|
|
94
|
+
type: "object",
|
|
95
|
+
description: "Full { cover?, docSettings?, sections: [] } payload. Preserve section ids unless you're intentionally deleting/inserting.",
|
|
96
|
+
},
|
|
97
|
+
title: { type: "string", description: "Optional — rename the doc at the same time." },
|
|
98
|
+
},
|
|
99
|
+
required: ["docId", "template_content"],
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "atlas_describe_section_type",
|
|
104
|
+
description: "Look up what fields a section type takes. Use this before atlas_update_section so you send the right shape. If called with no `type`, returns the full catalogue of known section types.",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: {
|
|
108
|
+
type: {
|
|
109
|
+
type: "string",
|
|
110
|
+
description: "e.g. 'moodboard', 'gear', 'text'. Omit to list all types.",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: "atlas_list_files",
|
|
117
|
+
description: "List files in the workspace-photos bucket (images, PDFs, videos). Returns { files, next_cursor } with storage paths + 1-hour signed URLs + alt text. To page through more, pass the previous next_cursor back in as `cursor`.",
|
|
118
|
+
inputSchema: {
|
|
119
|
+
type: "object",
|
|
120
|
+
properties: {
|
|
121
|
+
folder_id: { type: "string", description: "Optional folder id to filter by." },
|
|
122
|
+
limit: { type: "number", description: "Max rows (default 50, max 500)." },
|
|
123
|
+
cursor: {
|
|
124
|
+
type: "string",
|
|
125
|
+
description: "Opaque next_cursor from a previous response. Omit for the first page.",
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: "atlas_upload_file",
|
|
132
|
+
description: "Upload a local file (path on the user's machine) to the workspace bucket. Three-step signed-URL flow. Returns the storage path + a 1-hour signed URL. Extension whitelist enforced (images/video/audio/pdf/txt/md/json/csv); executables/archives refused.",
|
|
133
|
+
inputSchema: {
|
|
134
|
+
type: "object",
|
|
135
|
+
properties: {
|
|
136
|
+
local_path: {
|
|
137
|
+
type: "string",
|
|
138
|
+
description: "Absolute or CWD-relative path to a file on the machine running this MCP server.",
|
|
139
|
+
},
|
|
140
|
+
alt: { type: "string", description: "Alt text (≤ 300 chars)." },
|
|
141
|
+
},
|
|
142
|
+
required: ["local_path"],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "atlas_get_file_url",
|
|
147
|
+
description: "Return the 1-hour signed URL for one file by its storage path. Use this before dropping a URL into a gear row or moodboard tile.",
|
|
148
|
+
inputSchema: {
|
|
149
|
+
type: "object",
|
|
150
|
+
properties: {
|
|
151
|
+
path: { type: "string", description: "Full storage key returned by atlas_list_files or atlas_upload_file." },
|
|
152
|
+
},
|
|
153
|
+
required: ["path"],
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "atlas_set_file_alt",
|
|
158
|
+
description: "Update the alt text on a file. Pass null (or empty string) to clear.",
|
|
159
|
+
inputSchema: {
|
|
160
|
+
type: "object",
|
|
161
|
+
properties: {
|
|
162
|
+
path: { type: "string" },
|
|
163
|
+
alt: { type: "string", description: "New alt text. Empty string or omit to clear." },
|
|
164
|
+
},
|
|
165
|
+
required: ["path"],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "atlas_delete_file",
|
|
170
|
+
description: "Delete a file from the workspace bucket AND its metadata row. Destructive – no soft-delete.",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {
|
|
174
|
+
path: { type: "string" },
|
|
175
|
+
},
|
|
176
|
+
required: ["path"],
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "atlas_list_gear",
|
|
181
|
+
description: "List gear items (brand, name, quantity, photo) in the workspace. Returns { items, next_cursor }. Each item has a 1-hour signed image_url when it has an image. To page through more, pass the previous next_cursor back in as `cursor`.",
|
|
182
|
+
inputSchema: {
|
|
183
|
+
type: "object",
|
|
184
|
+
properties: {
|
|
185
|
+
limit: { type: "number", description: "Default 50, max 500." },
|
|
186
|
+
cursor: {
|
|
187
|
+
type: "string",
|
|
188
|
+
description: "Opaque next_cursor from a previous response. Omit for the first page.",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: "atlas_add_gear",
|
|
195
|
+
description: "Add a single gear item. For many items at once, use atlas_import_gear.",
|
|
196
|
+
inputSchema: {
|
|
197
|
+
type: "object",
|
|
198
|
+
properties: {
|
|
199
|
+
name: { type: "string", description: "Required. ≤ 160 chars." },
|
|
200
|
+
brand: { type: "string", description: "Optional. ≤ 80 chars." },
|
|
201
|
+
quantity: { type: "number", description: "Default 1, max 99999." },
|
|
202
|
+
image_path: {
|
|
203
|
+
type: "string",
|
|
204
|
+
description: "Optional. Storage key from atlas_upload_file. Must be in this workspace's prefix.",
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
required: ["name"],
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: "atlas_import_gear",
|
|
212
|
+
description: "Bulk-import gear rows in one shot. Faster than calling atlas_add_gear per item. `mode: 'replace'` clears the workspace's gear before inserting; `'append'` (default) adds on top.",
|
|
213
|
+
inputSchema: {
|
|
214
|
+
type: "object",
|
|
215
|
+
properties: {
|
|
216
|
+
mode: { type: "string", enum: ["append", "replace"] },
|
|
217
|
+
rows: {
|
|
218
|
+
type: "array",
|
|
219
|
+
description: "Up to 2000 rows. Each: { name (required), brand?, quantity?, image_path? }.",
|
|
220
|
+
items: {
|
|
221
|
+
type: "object",
|
|
222
|
+
properties: {
|
|
223
|
+
name: { type: "string" },
|
|
224
|
+
brand: { type: "string" },
|
|
225
|
+
quantity: { type: "number" },
|
|
226
|
+
image_path: { type: "string" },
|
|
227
|
+
},
|
|
228
|
+
required: ["name"],
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
required: ["rows"],
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: "atlas_delete_gear",
|
|
237
|
+
description: "Delete a gear item by id.",
|
|
238
|
+
inputSchema: {
|
|
239
|
+
type: "object",
|
|
240
|
+
properties: {
|
|
241
|
+
gearId: { type: "string" },
|
|
242
|
+
},
|
|
243
|
+
required: ["gearId"],
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: "atlas_update_gear",
|
|
248
|
+
description: "Update an existing gear item. Requires gear:update. Only provided fields are patched — send just the fields you want to change (name, brand, quantity, image_path).",
|
|
249
|
+
inputSchema: {
|
|
250
|
+
type: "object",
|
|
251
|
+
properties: {
|
|
252
|
+
gearId: { type: "string", description: "Gear item id from atlas_list_gear." },
|
|
253
|
+
name: { type: "string", description: "New item name (≤ 160 chars)." },
|
|
254
|
+
brand: { type: "string", description: "New brand (≤ 80 chars). Empty string clears." },
|
|
255
|
+
quantity: { type: "number", description: "New quantity (0–99999)." },
|
|
256
|
+
image_path: {
|
|
257
|
+
type: "string",
|
|
258
|
+
description: "Storage path from atlas_upload_file. Must live in this workspace's prefix. Empty string clears the image.",
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
required: ["gearId"],
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "atlas_rename_file",
|
|
266
|
+
description: "Rename a workspace file. Requires files:rename. Pass just the new filename — the workspace prefix + folder are preserved. Extension changes are refused server-side.",
|
|
267
|
+
inputSchema: {
|
|
268
|
+
type: "object",
|
|
269
|
+
properties: {
|
|
270
|
+
path: { type: "string", description: "Full storage key returned by atlas_list_files." },
|
|
271
|
+
new_name: { type: "string", description: "New filename only, no folder path. Keep the same extension." },
|
|
272
|
+
},
|
|
273
|
+
required: ["path", "new_name"],
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: "atlas_list_revisions",
|
|
278
|
+
description: "List revision history for a doc template. Requires templates:list-revisions. Returns revisions newest first with id, source (ui/api/cli), author, based_on_updated_at, created_at.",
|
|
279
|
+
inputSchema: {
|
|
280
|
+
type: "object",
|
|
281
|
+
properties: {
|
|
282
|
+
docId: { type: "string", description: "Doc id from atlas_list_docs." },
|
|
283
|
+
limit: { type: "number", description: "Max rows (default 50, max 200)." },
|
|
284
|
+
},
|
|
285
|
+
required: ["docId"],
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: "atlas_restore_revision",
|
|
290
|
+
description: "Restore a doc template to an earlier revision. Requires templates:restore-revision. Overwrites the current template_content. The pre-restore state is journaled first so the restore is itself reversible.",
|
|
291
|
+
inputSchema: {
|
|
292
|
+
type: "object",
|
|
293
|
+
properties: {
|
|
294
|
+
docId: { type: "string", description: "Doc id from atlas_list_docs." },
|
|
295
|
+
revisionId: { type: "string", description: "Revision id from atlas_list_revisions." },
|
|
296
|
+
},
|
|
297
|
+
required: ["docId", "revisionId"],
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
];
|
|
301
|
+
/* ─── Server setup ─────────────────────────────────────────────────── */
|
|
302
|
+
const server = new Server({ name: "atlas-mcp", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
303
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
304
|
+
tools: TOOLS,
|
|
305
|
+
}));
|
|
306
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
307
|
+
const name = req.params.name;
|
|
308
|
+
const args = (req.params.arguments ?? {});
|
|
309
|
+
try {
|
|
310
|
+
const result = await dispatch(name, args);
|
|
311
|
+
return {
|
|
312
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
catch (e) {
|
|
316
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
317
|
+
return {
|
|
318
|
+
isError: true,
|
|
319
|
+
content: [{ type: "text", text: `error: ${msg}` }],
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
async function dispatch(name, args) {
|
|
324
|
+
switch (name) {
|
|
325
|
+
case "atlas_list_docs":
|
|
326
|
+
return listDocs(args);
|
|
327
|
+
case "atlas_get_template":
|
|
328
|
+
return getTemplate(args);
|
|
329
|
+
case "atlas_list_sections":
|
|
330
|
+
return listSections(args);
|
|
331
|
+
case "atlas_update_section":
|
|
332
|
+
return updateSection(args);
|
|
333
|
+
case "atlas_list_files":
|
|
334
|
+
return listFiles(args);
|
|
335
|
+
case "atlas_upload_file":
|
|
336
|
+
return uploadFile(args);
|
|
337
|
+
case "atlas_get_file_url":
|
|
338
|
+
return getFileUrl(args);
|
|
339
|
+
case "atlas_set_file_alt":
|
|
340
|
+
return setFileAlt(args);
|
|
341
|
+
case "atlas_delete_file":
|
|
342
|
+
return deleteFile(args);
|
|
343
|
+
case "atlas_list_gear":
|
|
344
|
+
return listGear(args);
|
|
345
|
+
case "atlas_add_gear":
|
|
346
|
+
return addGear(args);
|
|
347
|
+
case "atlas_import_gear":
|
|
348
|
+
return importGear(args);
|
|
349
|
+
case "atlas_delete_gear":
|
|
350
|
+
return deleteGear(args);
|
|
351
|
+
case "atlas_update_template":
|
|
352
|
+
return updateTemplate(args);
|
|
353
|
+
case "atlas_describe_section_type":
|
|
354
|
+
return describeSectionType(args);
|
|
355
|
+
case "atlas_update_gear":
|
|
356
|
+
return updateGear(args);
|
|
357
|
+
case "atlas_rename_file":
|
|
358
|
+
return renameFile(args);
|
|
359
|
+
case "atlas_list_revisions":
|
|
360
|
+
return listRevisions(args);
|
|
361
|
+
case "atlas_restore_revision":
|
|
362
|
+
return restoreRevision(args);
|
|
363
|
+
default:
|
|
364
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/* ─── Tool implementations ─────────────────────────────────────────── */
|
|
368
|
+
async function listDocs(args) {
|
|
369
|
+
const cfg = resolveConfig();
|
|
370
|
+
const query = {};
|
|
371
|
+
if (typeof args.kind === "string")
|
|
372
|
+
query.kind = args.kind;
|
|
373
|
+
if (typeof args.limit === "number")
|
|
374
|
+
query.limit = args.limit;
|
|
375
|
+
if (typeof args.cursor === "string")
|
|
376
|
+
query.cursor = args.cursor;
|
|
377
|
+
const { data } = await apiRequest(cfg, "/api/v1/docs", { query });
|
|
378
|
+
return data;
|
|
379
|
+
}
|
|
380
|
+
async function getTemplate(args) {
|
|
381
|
+
const cfg = resolveConfig();
|
|
382
|
+
const docId = requireString(args, "docId");
|
|
383
|
+
const { data } = await apiRequest(cfg, `/api/v1/docs/${docId}/template`);
|
|
384
|
+
return data;
|
|
385
|
+
}
|
|
386
|
+
async function listSections(args) {
|
|
387
|
+
const tpl = await getTemplate(args);
|
|
388
|
+
const sections = tpl.template_content?.sections ?? [];
|
|
389
|
+
const summary = sections.map((s) => ({
|
|
390
|
+
id: s.id,
|
|
391
|
+
type: s.type,
|
|
392
|
+
// Best-effort title extraction — most sections stash a title on data.title.
|
|
393
|
+
title: (s.data && typeof s.data.title === "string"
|
|
394
|
+
? s.data.title
|
|
395
|
+
: null) ?? "",
|
|
396
|
+
hidden: !!s.hidden,
|
|
397
|
+
}));
|
|
398
|
+
return { docId: tpl.id, title: tpl.title, section_count: summary.length, sections: summary };
|
|
399
|
+
}
|
|
400
|
+
async function updateSection(args) {
|
|
401
|
+
const cfg = resolveConfig();
|
|
402
|
+
const docId = requireString(args, "docId");
|
|
403
|
+
const sectionId = requireString(args, "sectionId");
|
|
404
|
+
const newData = args.data;
|
|
405
|
+
if (!isRecord(newData))
|
|
406
|
+
throw new Error("`data` must be an object.");
|
|
407
|
+
const newStyle = isRecord(args.style) ? args.style : null;
|
|
408
|
+
const current = await getTemplate({ docId });
|
|
409
|
+
const template = current.template_content;
|
|
410
|
+
const sections = template.sections ?? [];
|
|
411
|
+
const idx = sections.findIndex((s) => s.id === sectionId);
|
|
412
|
+
if (idx === -1) {
|
|
413
|
+
throw new Error(`Section '${sectionId}' not found in doc '${docId}'. Call atlas_list_sections to see current section ids.`);
|
|
414
|
+
}
|
|
415
|
+
const patched = { ...sections[idx], data: newData };
|
|
416
|
+
if (newStyle) {
|
|
417
|
+
patched.style = { ...(sections[idx].style ?? {}), ...newStyle };
|
|
418
|
+
}
|
|
419
|
+
const nextSections = [...sections];
|
|
420
|
+
nextSections[idx] = patched;
|
|
421
|
+
const { data } = await apiRequest(cfg, `/api/v1/docs/${docId}/template`, {
|
|
422
|
+
method: "PUT",
|
|
423
|
+
body: { template_content: { ...template, sections: nextSections } },
|
|
424
|
+
ifMatch: current.etag,
|
|
425
|
+
});
|
|
426
|
+
return {
|
|
427
|
+
updated_section: sectionId,
|
|
428
|
+
etag: data.etag,
|
|
429
|
+
updated_at: data.updated_at,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
async function updateTemplate(args) {
|
|
433
|
+
const cfg = resolveConfig();
|
|
434
|
+
const docId = requireString(args, "docId");
|
|
435
|
+
const templateContent = args.template_content;
|
|
436
|
+
if (!isRecord(templateContent)) {
|
|
437
|
+
throw new Error("`template_content` must be an object matching TemplateContent shape.");
|
|
438
|
+
}
|
|
439
|
+
const title = typeof args.title === "string" ? args.title : undefined;
|
|
440
|
+
// Get-then-put for etag freshness.
|
|
441
|
+
const current = await getTemplate({ docId });
|
|
442
|
+
try {
|
|
443
|
+
const { data } = await apiRequest(cfg, `/api/v1/docs/${docId}/template`, {
|
|
444
|
+
method: "PUT",
|
|
445
|
+
body: { template_content: templateContent, ...(title ? { title } : {}) },
|
|
446
|
+
ifMatch: current.etag,
|
|
447
|
+
});
|
|
448
|
+
return {
|
|
449
|
+
docId: data.id,
|
|
450
|
+
title: data.title,
|
|
451
|
+
etag: data.etag,
|
|
452
|
+
updated_at: data.updated_at,
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
catch (e) {
|
|
456
|
+
if (e instanceof ApiError && e.status === 409) {
|
|
457
|
+
throw new Error("Doc was modified since we fetched it — re-run atlas_get_template to pick up the concurrent change, then retry.");
|
|
458
|
+
}
|
|
459
|
+
throw e;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async function describeSectionType(args) {
|
|
463
|
+
const type = args.type;
|
|
464
|
+
if (typeof type === "string") {
|
|
465
|
+
const entry = findSection(type);
|
|
466
|
+
if (!entry) {
|
|
467
|
+
throw new Error(`Unknown section type '${type}'. Known types: ${SECTION_CATALOG.map((s) => s.type).join(", ")}.`);
|
|
468
|
+
}
|
|
469
|
+
return entry;
|
|
470
|
+
}
|
|
471
|
+
return { types: SECTION_CATALOG };
|
|
472
|
+
}
|
|
473
|
+
/* ─── Files tools ──────────────────────────────────────────────────── */
|
|
474
|
+
async function listFiles(args) {
|
|
475
|
+
const cfg = resolveConfig();
|
|
476
|
+
const query = {};
|
|
477
|
+
if (typeof args.folder_id === "string")
|
|
478
|
+
query.folder_id = args.folder_id;
|
|
479
|
+
if (typeof args.limit === "number")
|
|
480
|
+
query.limit = args.limit;
|
|
481
|
+
if (typeof args.cursor === "string")
|
|
482
|
+
query.cursor = args.cursor;
|
|
483
|
+
const { data } = await apiRequest(cfg, "/api/v1/files", { query });
|
|
484
|
+
return data;
|
|
485
|
+
}
|
|
486
|
+
async function uploadFile(args) {
|
|
487
|
+
const cfg = resolveConfig();
|
|
488
|
+
const localPath = requireString(args, "local_path");
|
|
489
|
+
const alt = typeof args.alt === "string" ? args.alt : undefined;
|
|
490
|
+
const { readFile, stat } = await import("node:fs/promises");
|
|
491
|
+
const { basename, extname } = await import("node:path");
|
|
492
|
+
const info = await stat(localPath);
|
|
493
|
+
if (!info.isFile())
|
|
494
|
+
throw new Error(`Not a file: ${localPath}`);
|
|
495
|
+
const filename = basename(localPath);
|
|
496
|
+
const ext = extname(filename).toLowerCase();
|
|
497
|
+
const contentTypes = {
|
|
498
|
+
".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg",
|
|
499
|
+
".gif": "image/gif", ".webp": "image/webp", ".svg": "image/svg+xml",
|
|
500
|
+
".mp4": "video/mp4", ".mov": "video/quicktime", ".pdf": "application/pdf",
|
|
501
|
+
".txt": "text/plain", ".md": "text/markdown", ".json": "application/json",
|
|
502
|
+
".csv": "text/csv",
|
|
503
|
+
};
|
|
504
|
+
const contentType = contentTypes[ext] ?? "application/octet-stream";
|
|
505
|
+
// Step 1: signed URL
|
|
506
|
+
const { data: signRes } = await apiRequest(cfg, "/api/v1/files/upload-url", {
|
|
507
|
+
method: "POST",
|
|
508
|
+
body: { filename },
|
|
509
|
+
});
|
|
510
|
+
// Step 2: PUT bytes
|
|
511
|
+
const bytes = await readFile(localPath);
|
|
512
|
+
const putRes = await fetch(signRes.upload_url, {
|
|
513
|
+
method: "PUT",
|
|
514
|
+
headers: { "Content-Type": contentType, "x-upsert": "false" },
|
|
515
|
+
body: bytes,
|
|
516
|
+
});
|
|
517
|
+
if (!putRes.ok) {
|
|
518
|
+
const text = await putRes.text().catch(() => "");
|
|
519
|
+
throw new Error(`Storage upload failed (HTTP ${putRes.status}): ${text.slice(0, 200)}`);
|
|
520
|
+
}
|
|
521
|
+
// Step 3: register metadata
|
|
522
|
+
const { data: reg } = await apiRequest(cfg, "/api/v1/files", {
|
|
523
|
+
method: "POST",
|
|
524
|
+
body: { path: signRes.path, alt },
|
|
525
|
+
});
|
|
526
|
+
return {
|
|
527
|
+
path: signRes.path,
|
|
528
|
+
size: info.size,
|
|
529
|
+
content_type: contentType,
|
|
530
|
+
metadata: reg.file,
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
async function getFileUrl(args) {
|
|
534
|
+
const cfg = resolveConfig();
|
|
535
|
+
const path = requireString(args, "path");
|
|
536
|
+
const { data } = await apiRequest(cfg, "/api/v1/files", { query: { limit: 500 } });
|
|
537
|
+
const match = data.files.find((f) => f.path === path);
|
|
538
|
+
if (!match)
|
|
539
|
+
throw new Error(`File not found or no metadata row: ${path}`);
|
|
540
|
+
return { path: match.path, url: match.signed_url, alt: match.alt };
|
|
541
|
+
}
|
|
542
|
+
async function setFileAlt(args) {
|
|
543
|
+
const cfg = resolveConfig();
|
|
544
|
+
const path = requireString(args, "path");
|
|
545
|
+
const alt = typeof args.alt === "string" ? args.alt : null;
|
|
546
|
+
const { data } = await apiRequest(cfg, "/api/v1/files/alt", {
|
|
547
|
+
method: "POST",
|
|
548
|
+
body: { path, alt },
|
|
549
|
+
});
|
|
550
|
+
return data;
|
|
551
|
+
}
|
|
552
|
+
async function deleteFile(args) {
|
|
553
|
+
const cfg = resolveConfig();
|
|
554
|
+
const path = requireString(args, "path");
|
|
555
|
+
const { data } = await apiRequest(cfg, "/api/v1/files", {
|
|
556
|
+
method: "DELETE",
|
|
557
|
+
query: { path },
|
|
558
|
+
});
|
|
559
|
+
return data;
|
|
560
|
+
}
|
|
561
|
+
/* ─── Gear tools ───────────────────────────────────────────────────── */
|
|
562
|
+
async function listGear(args) {
|
|
563
|
+
const cfg = resolveConfig();
|
|
564
|
+
const query = {};
|
|
565
|
+
if (typeof args.limit === "number")
|
|
566
|
+
query.limit = args.limit;
|
|
567
|
+
if (typeof args.cursor === "string")
|
|
568
|
+
query.cursor = args.cursor;
|
|
569
|
+
const { data } = await apiRequest(cfg, "/api/v1/gear", { query });
|
|
570
|
+
return data;
|
|
571
|
+
}
|
|
572
|
+
async function addGear(args) {
|
|
573
|
+
const cfg = resolveConfig();
|
|
574
|
+
const body = { name: requireString(args, "name") };
|
|
575
|
+
if (typeof args.brand === "string")
|
|
576
|
+
body.brand = args.brand;
|
|
577
|
+
if (typeof args.quantity === "number")
|
|
578
|
+
body.quantity = args.quantity;
|
|
579
|
+
if (typeof args.image_path === "string")
|
|
580
|
+
body.image_path = args.image_path;
|
|
581
|
+
const { data } = await apiRequest(cfg, "/api/v1/gear", {
|
|
582
|
+
method: "POST",
|
|
583
|
+
body,
|
|
584
|
+
});
|
|
585
|
+
return data;
|
|
586
|
+
}
|
|
587
|
+
async function importGear(args) {
|
|
588
|
+
const cfg = resolveConfig();
|
|
589
|
+
const rows = args.rows;
|
|
590
|
+
if (!Array.isArray(rows))
|
|
591
|
+
throw new Error("`rows` must be an array.");
|
|
592
|
+
const mode = args.mode === "replace" ? "replace" : "append";
|
|
593
|
+
const { data } = await apiRequest(cfg, "/api/v1/gear/import", {
|
|
594
|
+
method: "POST",
|
|
595
|
+
body: { mode, rows },
|
|
596
|
+
});
|
|
597
|
+
return data;
|
|
598
|
+
}
|
|
599
|
+
async function deleteGear(args) {
|
|
600
|
+
const cfg = resolveConfig();
|
|
601
|
+
const gearId = requireString(args, "gearId");
|
|
602
|
+
const { data } = await apiRequest(cfg, `/api/v1/gear/${gearId}`, {
|
|
603
|
+
method: "DELETE",
|
|
604
|
+
});
|
|
605
|
+
return data;
|
|
606
|
+
}
|
|
607
|
+
async function updateGear(args) {
|
|
608
|
+
const cfg = resolveConfig();
|
|
609
|
+
const gearId = requireString(args, "gearId");
|
|
610
|
+
const body = {};
|
|
611
|
+
if (typeof args.name === "string")
|
|
612
|
+
body.name = args.name;
|
|
613
|
+
if (typeof args.brand === "string")
|
|
614
|
+
body.brand = args.brand;
|
|
615
|
+
if (typeof args.quantity === "number")
|
|
616
|
+
body.quantity = args.quantity;
|
|
617
|
+
if (typeof args.image_path === "string")
|
|
618
|
+
body.image_path = args.image_path;
|
|
619
|
+
if (Object.keys(body).length === 0) {
|
|
620
|
+
throw new Error("At least one of name, brand, quantity, image_path is required.");
|
|
621
|
+
}
|
|
622
|
+
const { data } = await apiRequest(cfg, `/api/v1/gear/${gearId}`, {
|
|
623
|
+
method: "PUT",
|
|
624
|
+
body,
|
|
625
|
+
});
|
|
626
|
+
return data;
|
|
627
|
+
}
|
|
628
|
+
/* ─── Files rename ─────────────────────────────────────────────────── */
|
|
629
|
+
async function renameFile(args) {
|
|
630
|
+
const cfg = resolveConfig();
|
|
631
|
+
const path = requireString(args, "path");
|
|
632
|
+
const newName = requireString(args, "new_name");
|
|
633
|
+
const { data } = await apiRequest(cfg, "/api/v1/files/rename", {
|
|
634
|
+
method: "POST",
|
|
635
|
+
body: { path, new_name: newName },
|
|
636
|
+
});
|
|
637
|
+
return data;
|
|
638
|
+
}
|
|
639
|
+
/* ─── Revisions ────────────────────────────────────────────────────── */
|
|
640
|
+
async function listRevisions(args) {
|
|
641
|
+
const cfg = resolveConfig();
|
|
642
|
+
const docId = requireString(args, "docId");
|
|
643
|
+
const query = {};
|
|
644
|
+
if (typeof args.limit === "number")
|
|
645
|
+
query.limit = args.limit;
|
|
646
|
+
const { data } = await apiRequest(cfg, `/api/v1/docs/${docId}/revisions`, { query });
|
|
647
|
+
return data;
|
|
648
|
+
}
|
|
649
|
+
async function restoreRevision(args) {
|
|
650
|
+
const cfg = resolveConfig();
|
|
651
|
+
const docId = requireString(args, "docId");
|
|
652
|
+
const revisionId = requireString(args, "revisionId");
|
|
653
|
+
const { data } = await apiRequest(cfg, `/api/v1/docs/${docId}/revisions/${revisionId}/restore`, {
|
|
654
|
+
method: "POST",
|
|
655
|
+
});
|
|
656
|
+
return {
|
|
657
|
+
docId: data.id,
|
|
658
|
+
title: data.title,
|
|
659
|
+
updated_at: data.updated_at,
|
|
660
|
+
etag: data.etag,
|
|
661
|
+
restored_from: data.restored_from,
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
/* ─── Helpers ──────────────────────────────────────────────────────── */
|
|
665
|
+
function requireString(args, key) {
|
|
666
|
+
const v = args[key];
|
|
667
|
+
if (typeof v !== "string" || !v)
|
|
668
|
+
throw new Error(`\`${key}\` is required.`);
|
|
669
|
+
return v;
|
|
670
|
+
}
|
|
671
|
+
function isRecord(v) {
|
|
672
|
+
return typeof v === "object" && v !== null;
|
|
673
|
+
}
|
|
674
|
+
/* ─── Boot ─────────────────────────────────────────────────────────── */
|
|
675
|
+
async function main() {
|
|
676
|
+
const transport = new StdioServerTransport();
|
|
677
|
+
await server.connect(transport);
|
|
678
|
+
// MCP: stderr is safe to log to; stdout is the framed protocol channel.
|
|
679
|
+
process.stderr.write("atlas-mcp: connected (stdio)\n");
|
|
680
|
+
}
|
|
681
|
+
main().catch((e) => {
|
|
682
|
+
process.stderr.write(`atlas-mcp: fatal: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
683
|
+
process.exit(1);
|
|
684
|
+
});
|
|
685
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable catalogue of Atlas doc-section types. Powers the
|
|
3
|
+
* `describe_section_type` MCP tool so Claude can look up what fields a
|
|
4
|
+
* section takes before editing it. Keep in lockstep with the app's
|
|
5
|
+
* `SectionType` union in `lib/doc-types.ts` — if a new type is added
|
|
6
|
+
* there, add it here so agents don't fly blind.
|
|
7
|
+
*
|
|
8
|
+
* These descriptions are deliberately terse: the model is smart enough
|
|
9
|
+
* to reason about the shape; what it needs is a nudge on the field
|
|
10
|
+
* *names* and *ranges*, not a full API doc.
|
|
11
|
+
*/
|
|
12
|
+
export const SECTION_CATALOG = [
|
|
13
|
+
{
|
|
14
|
+
type: "cover",
|
|
15
|
+
purpose: "Full-bleed cover page: title, subtitle, date, workspace lockup, optional hero image.",
|
|
16
|
+
data_shape: "Held on TemplateContent.cover, not on a section.data.",
|
|
17
|
+
common_fields: [
|
|
18
|
+
"subtitle: string",
|
|
19
|
+
"date: string (free-form or ISO)",
|
|
20
|
+
"bgImageUrl: string | null",
|
|
21
|
+
"titlePosition: '(top|middle|bottom)-(left|center|right)'",
|
|
22
|
+
"accentColor: hex",
|
|
23
|
+
"presentedBy: { enabled, showLogo, logoUrl, size, position, ... }",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: "toc",
|
|
28
|
+
purpose: "Table of contents with per-row labels, borders, alignment.",
|
|
29
|
+
data_shape: "section.data — { title, showNumbers, hideRows: string[], borders, columnStyle }",
|
|
30
|
+
common_fields: [
|
|
31
|
+
"title: string",
|
|
32
|
+
"hideRows: string[] (section ids to omit)",
|
|
33
|
+
"columnStyle: 'fixed' | 'flexible'",
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
purpose: "Unified text block (title + subtitle + body) with optional callout treatment.",
|
|
39
|
+
data_shape: "section.data — see lib/doc-types.ts. Legacy 'container' auto-migrates to this.",
|
|
40
|
+
common_fields: [
|
|
41
|
+
"title, subtitle, body: string",
|
|
42
|
+
"align/font/size/color per element",
|
|
43
|
+
"callout: bool + calloutTone: 'primary'|'accent'|'muted'|'custom'",
|
|
44
|
+
"bgColor, padding, radius",
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: "notes",
|
|
49
|
+
purpose: "Bullet list section (title + subtitle + bullets) with configurable markers.",
|
|
50
|
+
data_shape: "section.data — { title, subtitle, bullets: string[], bulletMarker, textSize, markerSize }",
|
|
51
|
+
common_fields: [
|
|
52
|
+
"bullets: string[]",
|
|
53
|
+
"bulletMarker: 'disc'|'circle'|'square'|'decimal'|'dash'|'arrow'|'check'|'custom'",
|
|
54
|
+
"bulletMarkerCustom: string (1-4 chars)",
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: "gear",
|
|
59
|
+
purpose: "Reference to workspace gear items — renders as table / bullets / images grid.",
|
|
60
|
+
data_shape: "section.data — { title, itemIds: string[], format: 'table'|'bullets'|'images', columns, ... }",
|
|
61
|
+
common_fields: [
|
|
62
|
+
"itemIds: uuid[] (from workspace gear library)",
|
|
63
|
+
"format: 'table' | 'bullets' | 'images'",
|
|
64
|
+
"columns: { photo, brand, quantity }",
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: "shot-list",
|
|
69
|
+
purpose: "Table of shots (name / kind / lens / notes).",
|
|
70
|
+
data_shape: "section.data — { title, rows: [{ name, kind, lens, notes }] }",
|
|
71
|
+
common_fields: ["rows: object[]"],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
type: "team",
|
|
75
|
+
purpose: "Crew grid (name + role). Optional join to workspace_members.",
|
|
76
|
+
data_shape: "section.data — { title, people: [{ name, role }] }",
|
|
77
|
+
common_fields: ["people: object[]"],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
type: "products",
|
|
81
|
+
purpose: "Shopify product references (placeholder — real integration is Phase 2).",
|
|
82
|
+
data_shape: "section.data — { title, products: ProductRef[] }",
|
|
83
|
+
common_fields: ["products: object[]"],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: "locations",
|
|
87
|
+
purpose: "Location list — address + optional map URL.",
|
|
88
|
+
data_shape: "section.data — { title, locations: LocationItem[] }",
|
|
89
|
+
common_fields: [
|
|
90
|
+
"locations: [{ label, address, notes?, mapUrl? }]",
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: "people-link",
|
|
95
|
+
purpose: "Mixed list of workspace members and external contacts.",
|
|
96
|
+
data_shape: "section.data — { title, people: LinkedPerson[] }",
|
|
97
|
+
common_fields: [
|
|
98
|
+
"people: [{ userId?, name, role?, email?, phone?, external? }]",
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
type: "table",
|
|
103
|
+
purpose: "Freeform header + rows.",
|
|
104
|
+
data_shape: "section.data — { title, header: string[], rows: { cells: string[] }[] }",
|
|
105
|
+
common_fields: ["rows: TableRow[]"],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
type: "moodboard",
|
|
109
|
+
purpose: "Image grid with configurable rows/cols/spacing/radius/aspect.",
|
|
110
|
+
data_shape: "section.data — { title, images: (MoodBoardImage|null)[], rows, cols, aspect, spacing, radius, ... }",
|
|
111
|
+
common_fields: [
|
|
112
|
+
"images: length === rows * cols (missing slots are null)",
|
|
113
|
+
"aspect: 'square' | 'portrait' | 'landscape'",
|
|
114
|
+
"rows, cols: number",
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: "palette",
|
|
119
|
+
purpose: "Colour palette extracted from a source moodboard (or manually curated).",
|
|
120
|
+
data_shape: "section.data — { title, sourceSectionId, rows, cols, extractedColours, ... }",
|
|
121
|
+
common_fields: [
|
|
122
|
+
"sourceSectionId: string (id of a moodboard section)",
|
|
123
|
+
"rows, cols: number",
|
|
124
|
+
"extractedColours: PaletteColour[]",
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
export function findSection(type) {
|
|
129
|
+
return SECTION_CATALOG.find((s) => s.type === type) ?? null;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=section-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-catalog.js","sourceRoot":"","sources":["../src/section-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,MAAM,CAAC,MAAM,eAAe,GAA0B;IACpD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,sFAAsF;QAC/F,UAAU,EAAE,uDAAuD;QACnE,aAAa,EAAE;YACb,kBAAkB;YAClB,iCAAiC;YACjC,2BAA2B;YAC3B,0DAA0D;YAC1D,kBAAkB;YAClB,kEAAkE;SACnE;KACF;IACD;QACE,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,4DAA4D;QACrE,UAAU,EAAE,iFAAiF;QAC7F,aAAa,EAAE;YACb,eAAe;YACf,0CAA0C;YAC1C,mCAAmC;SACpC;KACF;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,+EAA+E;QACxF,UAAU,EAAE,gFAAgF;QAC5F,aAAa,EAAE;YACb,+BAA+B;YAC/B,mCAAmC;YACnC,kEAAkE;YAClE,0BAA0B;SAC3B;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,6EAA6E;QACtF,UAAU,EAAE,2FAA2F;QACvG,aAAa,EAAE;YACb,mBAAmB;YACnB,kFAAkF;YAClF,wCAAwC;SACzC;KACF;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,+EAA+E;QACxF,UAAU,EAAE,+FAA+F;QAC3G,aAAa,EAAE;YACb,+CAA+C;YAC/C,wCAAwC;YACxC,qCAAqC;SACtC;KACF;IACD;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,8CAA8C;QACvD,UAAU,EAAE,+DAA+D;QAC3E,aAAa,EAAE,CAAC,gBAAgB,CAAC;KAClC;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,8DAA8D;QACvE,UAAU,EAAE,oDAAoD;QAChE,aAAa,EAAE,CAAC,kBAAkB,CAAC;KACpC;IACD;QACE,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,yEAAyE;QAClF,UAAU,EAAE,kDAAkD;QAC9D,aAAa,EAAE,CAAC,oBAAoB,CAAC;KACtC;IACD;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,6CAA6C;QACtD,UAAU,EAAE,qDAAqD;QACjE,aAAa,EAAE;YACb,kDAAkD;SACnD;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,wDAAwD;QACjE,UAAU,EAAE,kDAAkD;QAC9D,aAAa,EAAE;YACb,+DAA+D;SAChE;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,yBAAyB;QAClC,UAAU,EAAE,yEAAyE;QACrF,aAAa,EAAE,CAAC,kBAAkB,CAAC;KACpC;IACD;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,+DAA+D;QACxE,UAAU,EAAE,qGAAqG;QACjH,aAAa,EAAE;YACb,yDAAyD;YACzD,6CAA6C;YAC7C,oBAAoB;SACrB;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,yEAAyE;QAClF,UAAU,EAAE,8EAA8E;QAC1F,aAAa,EAAE;YACb,qDAAqD;YACrD,oBAAoB;YACpB,mCAAmC;SACpC;KACF;CACF,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC;AAC9D,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kezlahd/atlas-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for the Atlas creative-team platform – lets Claude Code and other AI agents edit doc templates, files, and gear.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Kieran Jackson",
|
|
8
|
+
"homepage": "https://atlas.mjsons.net",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/KezLahd/atlas.git",
|
|
12
|
+
"directory": "packages/atlas-mcp"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/KezLahd/atlas/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"atlas",
|
|
19
|
+
"mcp",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"claude",
|
|
22
|
+
"ai-tools",
|
|
23
|
+
"creative-team"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"atlas-mcp": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"dev": "tsx src/index.ts",
|
|
38
|
+
"build": "tsc",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"prepublishOnly": "tsc"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
44
|
+
"zod": "^3.24.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^20",
|
|
48
|
+
"tsx": "^4.19.2",
|
|
49
|
+
"typescript": "^5"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20"
|
|
53
|
+
}
|
|
54
|
+
}
|