@clipkit/mcp-server 1.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/LICENSE +201 -0
- package/README.md +67 -0
- package/dist/embedded-docs.d.ts +4 -0
- package/dist/embedded-docs.d.ts.map +1 -0
- package/dist/embedded-docs.js +3589 -0
- package/dist/embedded-docs.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +7 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +23 -0
- package/dist/lib.js.map +1 -0
- package/dist/project-store.d.ts +62 -0
- package/dist/project-store.d.ts.map +1 -0
- package/dist/project-store.js +89 -0
- package/dist/project-store.js.map +1 -0
- package/dist/resources.d.ts +3 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +76 -0
- package/dist/resources.js.map +1 -0
- package/dist/schema-json.d.ts +3 -0
- package/dist/schema-json.d.ts.map +1 -0
- package/dist/schema-json.js +29 -0
- package/dist/schema-json.js.map +1 -0
- package/dist/server-config.d.ts +10 -0
- package/dist/server-config.d.ts.map +1 -0
- package/dist/server-config.js +33 -0
- package/dist/server-config.js.map +1 -0
- package/dist/state.d.ts +20 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +49 -0
- package/dist/state.js.map +1 -0
- package/dist/tools.d.ts +15 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +1178 -0
- package/dist/tools.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-docs.js","sourceRoot":"","sources":["../src/embedded-docs.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,6DAA6D;AAC7D,sEAAsE;AAEtE,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAy8BxB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAowE1B,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiTvB,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,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// CLI entry for @clipkit/mcp-server.
|
|
3
|
+
//
|
|
4
|
+
// Starts an MCP server over stdio. The agent process (Claude Desktop,
|
|
5
|
+
// Cursor, etc.) spawns this binary, communicates via JSON-RPC on
|
|
6
|
+
// stdin/stdout, and we never write to stdout ourselves — diagnostic
|
|
7
|
+
// output goes to stderr.
|
|
8
|
+
//
|
|
9
|
+
// This is the stdio bin. Importing the package (`@clipkit/mcp-server`) resolves
|
|
10
|
+
// to the library entry (lib.ts) — the building blocks for hosting the server
|
|
11
|
+
// behind an HTTP route — WITHOUT this stdio bootstrap.
|
|
12
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
13
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
14
|
+
import { InMemoryProjectStore } from './project-store.js';
|
|
15
|
+
import { registerTools } from './tools.js';
|
|
16
|
+
import { registerResources } from './resources.js';
|
|
17
|
+
import { SERVER_INFO, SERVER_CAPABILITIES, SERVER_INSTRUCTIONS } from './server-config.js';
|
|
18
|
+
async function main() {
|
|
19
|
+
const server = new McpServer(SERVER_INFO, {
|
|
20
|
+
capabilities: SERVER_CAPABILITIES,
|
|
21
|
+
instructions: SERVER_INSTRUCTIONS,
|
|
22
|
+
});
|
|
23
|
+
// Local stdio: one in-memory project per process. project_id is optional and
|
|
24
|
+
// defaults to this single "current" project. (A hosted, sessionless server
|
|
25
|
+
// injects a Supabase-backed store and requires explicit project_ids instead.)
|
|
26
|
+
const store = new InMemoryProjectStore();
|
|
27
|
+
registerTools(server, store);
|
|
28
|
+
registerResources(server);
|
|
29
|
+
const transport = new StdioServerTransport();
|
|
30
|
+
await server.connect(transport);
|
|
31
|
+
process.stderr.write('[clipkit-mcp] ready (tools + resources)\n');
|
|
32
|
+
}
|
|
33
|
+
main().catch((err) => {
|
|
34
|
+
process.stderr.write(`[clipkit-mcp] fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,qCAAqC;AACrC,EAAE;AACF,sEAAsE;AACtE,iEAAiE;AACjE,oEAAoE;AACpE,yBAAyB;AACzB,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,uDAAuD;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE3F,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,WAAW,EAAE;QACxC,YAAY,EAAE,mBAAmB;QACjC,YAAY,EAAE,mBAAmB;KAClC,CAAC,CAAC;IAEH,6EAA6E;IAC7E,2EAA2E;IAC3E,8EAA8E;IAC9E,MAAM,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAC;IACzC,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;AACpE,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wBAAwB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC1F,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/lib.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { registerTools } from './tools.js';
|
|
2
|
+
export { registerResources } from './resources.js';
|
|
3
|
+
export { SERVER_INFO, SERVER_CAPABILITIES, SERVER_INSTRUCTIONS } from './server-config.js';
|
|
4
|
+
export { type ProjectStore, type OpenProject, openProject, InMemoryProjectStore, } from './project-store.js';
|
|
5
|
+
export { blankSource, cloneSource, locateElement, type ElementLocation } from './state.js';
|
|
6
|
+
export { SOURCE_SCHEMA_JSON, elementSchemaJson } from './schema-json.js';
|
|
7
|
+
//# sourceMappingURL=lib.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,WAAW,EACX,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/lib.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Library entry for @clipkit/mcp-server.
|
|
2
|
+
//
|
|
3
|
+
// Importing the package (`@clipkit/mcp-server`) gives these building blocks for
|
|
4
|
+
// HOSTING the server — e.g. behind a stateless HTTP route — WITHOUT the stdio
|
|
5
|
+
// bootstrap that runs on import of index.ts. The stdio CLI remains the package
|
|
6
|
+
// `bin` and the `./stdio` subpath export.
|
|
7
|
+
//
|
|
8
|
+
// A host wires it up the same way index.ts does, but with its own transport and
|
|
9
|
+
// (typically) a non-in-memory ProjectStore:
|
|
10
|
+
//
|
|
11
|
+
// const server = new McpServer(SERVER_INFO, {
|
|
12
|
+
// capabilities: SERVER_CAPABILITIES,
|
|
13
|
+
// instructions: SERVER_INSTRUCTIONS,
|
|
14
|
+
// });
|
|
15
|
+
// registerTools(server, store); // store implements ProjectStore
|
|
16
|
+
// registerResources(server);
|
|
17
|
+
export { registerTools } from './tools.js';
|
|
18
|
+
export { registerResources } from './resources.js';
|
|
19
|
+
export { SERVER_INFO, SERVER_CAPABILITIES, SERVER_INSTRUCTIONS } from './server-config.js';
|
|
20
|
+
export { openProject, InMemoryProjectStore, } from './project-store.js';
|
|
21
|
+
export { blankSource, cloneSource, locateElement } from './state.js';
|
|
22
|
+
export { SOURCE_SCHEMA_JSON, elementSchemaJson } from './schema-json.js';
|
|
23
|
+
//# sourceMappingURL=lib.js.map
|
package/dist/lib.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,0CAA0C;AAC1C,EAAE;AACF,gFAAgF;AAChF,4CAA4C;AAC5C,EAAE;AACF,gDAAgD;AAChD,yCAAyC;AACzC,yCAAyC;AACzC,QAAQ;AACR,qEAAqE;AACrE,+BAA+B;AAE/B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAGL,WAAW,EACX,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAwB,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Source } from '@clipkit/protocol';
|
|
2
|
+
export interface ProjectStore {
|
|
3
|
+
/**
|
|
4
|
+
* Create or replace a project's source.
|
|
5
|
+
* - `id` given → replace that project's source.
|
|
6
|
+
* - `id` omitted → create a new project. Single-tenant stores MAY reuse a
|
|
7
|
+
* "current" slot; multi-tenant stores mint a fresh id.
|
|
8
|
+
* Returns the project's id.
|
|
9
|
+
*/
|
|
10
|
+
put(id: string | undefined, source: Source): Promise<string>;
|
|
11
|
+
/** Load a project's source by id, or null if it is absent/expired. */
|
|
12
|
+
get(id: string): Promise<Source | null>;
|
|
13
|
+
/**
|
|
14
|
+
* The id a tool should act on when the caller omitted project_id.
|
|
15
|
+
* Single-tenant in-memory → the current project; multi-tenant → null
|
|
16
|
+
* (callers must pass an explicit project_id).
|
|
17
|
+
*/
|
|
18
|
+
currentId(): Promise<string | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Optional. If this store's rows ARE the editor's source of truth (a hosted DB
|
|
21
|
+
* store), return the editor URL for an existing project id, so open_in_editor /
|
|
22
|
+
* create_promo can link straight to it — no snapshot copy. Return null when the
|
|
23
|
+
* store can't surface a link itself (the in-memory stdio store), in which case
|
|
24
|
+
* the caller persists a share via the API instead.
|
|
25
|
+
*/
|
|
26
|
+
editorUrl?(projectId: string): Promise<string | null>;
|
|
27
|
+
}
|
|
28
|
+
/** A loaded project plus a save() already bound to its id. */
|
|
29
|
+
export interface OpenProject {
|
|
30
|
+
id: string;
|
|
31
|
+
source: Source;
|
|
32
|
+
save: (next: Source) => Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve project_id (or the store's current project), load it, and hand back a
|
|
36
|
+
* bound save(). Returns an error string for the tool to surface if there is no
|
|
37
|
+
* such project — this is the single place the "missing/expired id" guidance
|
|
38
|
+
* lives, so every tool reports it consistently.
|
|
39
|
+
*/
|
|
40
|
+
export declare function openProject(store: ProjectStore, projectId: string | undefined): Promise<{
|
|
41
|
+
ok: true;
|
|
42
|
+
project: OpenProject;
|
|
43
|
+
} | {
|
|
44
|
+
ok: false;
|
|
45
|
+
error: string;
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* In-memory store: one process, projects held in a Map. The default for local
|
|
49
|
+
* stdio. Seeds a blank "current" project so a fresh session can get_project /
|
|
50
|
+
* edit immediately and project_id stays optional locally.
|
|
51
|
+
*/
|
|
52
|
+
export declare class InMemoryProjectStore implements ProjectStore {
|
|
53
|
+
private projects;
|
|
54
|
+
private current;
|
|
55
|
+
private seq;
|
|
56
|
+
constructor(seedBlank?: boolean);
|
|
57
|
+
put(id: string | undefined, source: Source): Promise<string>;
|
|
58
|
+
get(id: string): Promise<Source | null>;
|
|
59
|
+
currentId(): Promise<string | null>;
|
|
60
|
+
private mint;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=project-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-store.d.ts","sourceRoot":"","sources":["../src/project-store.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7D,sEAAsE;IACtE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAExC;;;;OAIG;IACH,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEpC;;;;;;OAMG;IACH,SAAS,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvD;AAED,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA2B5E;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,GAAG,CAAK;gBAEJ,SAAS,UAAO;IAQtB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ5D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKvC,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzC,OAAO,CAAC,IAAI;CAIb"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// ProjectStore — the persistence seam for MCP project state.
|
|
2
|
+
//
|
|
3
|
+
// Tools don't hold a Source; they ask the store to load/save one by id. That
|
|
4
|
+
// indirection is what lets the same tool code run two very different ways:
|
|
5
|
+
//
|
|
6
|
+
// • local stdio — one in-memory project per process (InMemoryProjectStore).
|
|
7
|
+
// project_id is optional and defaults to the single "current" project, so
|
|
8
|
+
// the local UX is unchanged: create_project / set_project then edit.
|
|
9
|
+
//
|
|
10
|
+
// • hosted HTTP — many concurrent projects in a shared DB, the server fully
|
|
11
|
+
// SESSIONLESS. Each tool call carries an explicit project_id; the Supabase
|
|
12
|
+
// adapter (in apps/web) returns null from currentId(), so a missing id is a
|
|
13
|
+
// clear error rather than a cross-tenant guess.
|
|
14
|
+
//
|
|
15
|
+
// Going sessionless (no Mcp-Session-Id) and keying on a client-supplied
|
|
16
|
+
// project_id is both the most portable choice across MCP clients (Codex,
|
|
17
|
+
// Gemini CLI, Cursor, Cline, …) and the direction the spec is moving — the
|
|
18
|
+
// 2026-07-28 release candidate drops protocol sessions entirely so "any MCP
|
|
19
|
+
// request can land on any server instance" without a shared session store.
|
|
20
|
+
import { blankSource, cloneSource } from './state.js';
|
|
21
|
+
/**
|
|
22
|
+
* Resolve project_id (or the store's current project), load it, and hand back a
|
|
23
|
+
* bound save(). Returns an error string for the tool to surface if there is no
|
|
24
|
+
* such project — this is the single place the "missing/expired id" guidance
|
|
25
|
+
* lives, so every tool reports it consistently.
|
|
26
|
+
*/
|
|
27
|
+
export async function openProject(store, projectId) {
|
|
28
|
+
const id = projectId ?? (await store.currentId());
|
|
29
|
+
if (!id) {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
error: 'No active project. Create one with create_project or set_project, then pass the ' +
|
|
33
|
+
'returned project_id to subsequent tools.',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const source = await store.get(id);
|
|
37
|
+
if (!source) {
|
|
38
|
+
return {
|
|
39
|
+
ok: false,
|
|
40
|
+
error: `No project "${id}" (it may have expired). Pass a valid project_id, or create a new project.`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
ok: true,
|
|
45
|
+
project: {
|
|
46
|
+
id,
|
|
47
|
+
source,
|
|
48
|
+
save: async (next) => {
|
|
49
|
+
await store.put(id, next);
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* In-memory store: one process, projects held in a Map. The default for local
|
|
56
|
+
* stdio. Seeds a blank "current" project so a fresh session can get_project /
|
|
57
|
+
* edit immediately and project_id stays optional locally.
|
|
58
|
+
*/
|
|
59
|
+
export class InMemoryProjectStore {
|
|
60
|
+
projects = new Map();
|
|
61
|
+
current = null;
|
|
62
|
+
seq = 0;
|
|
63
|
+
constructor(seedBlank = true) {
|
|
64
|
+
if (seedBlank) {
|
|
65
|
+
const id = this.mint();
|
|
66
|
+
this.projects.set(id, blankSource());
|
|
67
|
+
this.current = id;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async put(id, source) {
|
|
71
|
+
const pid = id ?? this.current ?? this.mint();
|
|
72
|
+
// Store an isolated copy so the caller's object can't mutate saved state.
|
|
73
|
+
this.projects.set(pid, cloneSource(source));
|
|
74
|
+
this.current = pid;
|
|
75
|
+
return pid;
|
|
76
|
+
}
|
|
77
|
+
async get(id) {
|
|
78
|
+
const src = this.projects.get(id);
|
|
79
|
+
return src ? cloneSource(src) : null;
|
|
80
|
+
}
|
|
81
|
+
async currentId() {
|
|
82
|
+
return this.current;
|
|
83
|
+
}
|
|
84
|
+
mint() {
|
|
85
|
+
this.seq += 1;
|
|
86
|
+
return `proj_${this.seq}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=project-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-store.js","sourceRoot":"","sources":["../src/project-store.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,yEAAyE;AACzE,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,gFAAgF;AAChF,oDAAoD;AACpD,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,2EAA2E;AAC3E,4EAA4E;AAC5E,2EAA2E;AAG3E,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAuCtD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAmB,EACnB,SAA6B;IAE7B,MAAM,EAAE,GAAG,SAAS,IAAI,CAAC,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EACH,kFAAkF;gBAClF,0CAA0C;SAC7C,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,eAAe,EAAE,4EAA4E;SACrG,CAAC;IACJ,CAAC;IACD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE;YACP,EAAE;YACF,MAAM;YACN,IAAI,EAAE,KAAK,EAAE,IAAY,EAAE,EAAE;gBAC3B,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC5B,CAAC;SACF;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,oBAAoB;IACvB,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrC,OAAO,GAAkB,IAAI,CAAC;IAC9B,GAAG,GAAG,CAAC,CAAC;IAEhB,YAAY,SAAS,GAAG,IAAI;QAC1B,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;YACrC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAsB,EAAE,MAAc;QAC9C,MAAM,GAAG,GAAG,EAAE,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC9C,0EAA0E;QAC1E,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,OAAO,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuDzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsCzD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// MCP resources exposed by the Clipkit server.
|
|
2
|
+
//
|
|
3
|
+
// These are read-only docs the client can list and fetch on demand. They
|
|
4
|
+
// give an AI agent (Claude Desktop, Cursor in MCP mode, etc.) the same
|
|
5
|
+
// authoring context a human would get by browsing the repo:
|
|
6
|
+
//
|
|
7
|
+
// clipkit://docs/agents.md — AGENTS.md (authoring guide)
|
|
8
|
+
// clipkit://docs/protocol.md — PROTOCOL.md (CKP/1.0 spec)
|
|
9
|
+
// clipkit://docs/brand.md — BRAND.md (brand reference)
|
|
10
|
+
//
|
|
11
|
+
// Contents are embedded at build time (see scripts/embed-docs.mjs) so
|
|
12
|
+
// the server is self-contained — no FS access required at runtime.
|
|
13
|
+
import { AGENTS_MD, PROTOCOL_MD, BRAND_MD } from './embedded-docs.js';
|
|
14
|
+
import { SOURCE_SCHEMA_JSON } from './schema-json.js';
|
|
15
|
+
const DOCS = [
|
|
16
|
+
{
|
|
17
|
+
name: 'clipkit-agents',
|
|
18
|
+
uri: 'clipkit://docs/agents.md',
|
|
19
|
+
title: 'Clipkit — Authoring guide (AGENTS.md)',
|
|
20
|
+
description: 'AI authoring reference for Clipkit videos. Schema cheat sheet, ' +
|
|
21
|
+
'pattern catalog (HeaderBar / StatBlock / BarChartRow / RankedList / ' +
|
|
22
|
+
'PieCard), recipe gallery pointing at the working example videos, ' +
|
|
23
|
+
'and authoring guidance (pacing, count-ups, staggers). Read this ' +
|
|
24
|
+
'before composing a video.',
|
|
25
|
+
content: AGENTS_MD,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'clipkit-protocol',
|
|
29
|
+
uri: 'clipkit://docs/protocol.md',
|
|
30
|
+
title: 'Clipkit Protocol v1.0 (PROTOCOL.md)',
|
|
31
|
+
description: 'Normative specification for the Clipkit Protocol (CKP/1.0). RFC ' +
|
|
32
|
+
'2119 voice — defines Source structure, every element type, the ' +
|
|
33
|
+
'animation model, easing functions, conformance levels (validate / ' +
|
|
34
|
+
'render / export), versioning, and the extension namespace. Source ' +
|
|
35
|
+
'of truth for implementers.',
|
|
36
|
+
content: PROTOCOL_MD,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'clipkit-brand',
|
|
40
|
+
uri: 'clipkit://docs/brand.md',
|
|
41
|
+
title: 'Clipkit Brand reference (BRAND.md)',
|
|
42
|
+
description: 'Brand identity: dark surface system (#0A0A0A), two accents only ' +
|
|
43
|
+
'(red #EF4444 + yellow #FFB800), Geist + Geist Mono typography, the ' +
|
|
44
|
+
'three-bar logo construction, voice & tone (direct / concrete / ' +
|
|
45
|
+
'honest / no hype). Use when producing Clipkit-branded assets.',
|
|
46
|
+
content: BRAND_MD,
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
export function registerResources(server) {
|
|
50
|
+
for (const doc of DOCS) {
|
|
51
|
+
server.registerResource(doc.name, doc.uri, {
|
|
52
|
+
title: doc.title,
|
|
53
|
+
description: doc.description,
|
|
54
|
+
mimeType: 'text/markdown',
|
|
55
|
+
}, async (uri) => ({
|
|
56
|
+
contents: [
|
|
57
|
+
{
|
|
58
|
+
uri: uri.href,
|
|
59
|
+
mimeType: 'text/markdown',
|
|
60
|
+
text: doc.content,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
server.registerResource('clipkit-schema', 'clipkit://schema/source.json', {
|
|
66
|
+
title: 'Clipkit Source — JSON Schema',
|
|
67
|
+
description: 'Machine-readable JSON Schema for a Clipkit Source, generated from the protocol Zod source ' +
|
|
68
|
+
'of truth. The EXACT shape for set_project / add_element — every field, every element type, ' +
|
|
69
|
+
'with types and enums. Read it to author correct JSON instead of guessing field names. ' +
|
|
70
|
+
'(Agents that cannot read resources: use the get_schema tool instead.)',
|
|
71
|
+
mimeType: 'application/json',
|
|
72
|
+
}, async (uri) => ({
|
|
73
|
+
contents: [{ uri: uri.href, mimeType: 'application/json', text: SOURCE_SCHEMA_JSON }],
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,4DAA4D;AAC5D,EAAE;AACF,+DAA+D;AAC/D,8DAA8D;AAC9D,8DAA8D;AAC9D,EAAE;AACF,sEAAsE;AACtE,mEAAmE;AAGnE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAetD,MAAM,IAAI,GAAkB;IAC1B;QACE,IAAI,EAAE,gBAAgB;QACtB,GAAG,EAAE,0BAA0B;QAC/B,KAAK,EAAE,uCAAuC;QAC9C,WAAW,EACT,iEAAiE;YACjE,sEAAsE;YACtE,mEAAmE;YACnE,kEAAkE;YAClE,2BAA2B;QAC7B,OAAO,EAAE,SAAS;KACnB;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,GAAG,EAAE,4BAA4B;QACjC,KAAK,EAAE,qCAAqC;QAC5C,WAAW,EACT,kEAAkE;YAClE,iEAAiE;YACjE,oEAAoE;YACpE,oEAAoE;YACpE,4BAA4B;QAC9B,OAAO,EAAE,WAAW;KACrB;IACD;QACE,IAAI,EAAE,eAAe;QACrB,GAAG,EAAE,yBAAyB;QAC9B,KAAK,EAAE,oCAAoC;QAC3C,WAAW,EACT,kEAAkE;YAClE,qEAAqE;YACrE,iEAAiE;YACjE,+DAA+D;QACjE,OAAO,EAAE,QAAQ;KAClB;CACF,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,gBAAgB,CACrB,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,GAAG,EACP;YACE,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,QAAQ,EAAE,eAAe;SAC1B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACd,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,eAAe;oBACzB,IAAI,EAAE,GAAG,CAAC,OAAO;iBAClB;aACF;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,gBAAgB,CACrB,gBAAgB,EAChB,8BAA8B,EAC9B;QACE,KAAK,EAAE,8BAA8B;QACrC,WAAW,EACT,4FAA4F;YAC5F,6FAA6F;YAC7F,wFAAwF;YACxF,uEAAuE;QACzE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;KACtF,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-json.d.ts","sourceRoot":"","sources":["../src/schema-json.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,kBAAkB,QAE9B,CAAC;AAkBF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// JSON Schema for the Clipkit Source, generated from the protocol's Zod source
|
|
2
|
+
// of truth (same as `clipkit schema`). Exposed to agents via the get_schema TOOL
|
|
3
|
+
// — MCP *resources* aren't model-readable in clients like Claude Desktop (they're
|
|
4
|
+
// user-attached), so a tool is the only reliable way to hand the agent the schema.
|
|
5
|
+
//
|
|
6
|
+
// Both the full Source schema and per-element-type schemas are precomputed once.
|
|
7
|
+
import { sourceSchema, elementSchema } from '@clipkit/protocol';
|
|
8
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
9
|
+
// Compact (no indentation): at this nesting depth ~60% of a pretty-printed schema is
|
|
10
|
+
// leading whitespace, and the agent parses compact JSON fine. The human-facing
|
|
11
|
+
// `clipkit schema` CLI can pretty-print separately if a person needs to read it.
|
|
12
|
+
export const SOURCE_SCHEMA_JSON = JSON.stringify(zodToJsonSchema(sourceSchema, { name: 'ClipkitSource', $refStrategy: 'relative' }));
|
|
13
|
+
// Per-type element schemas (much smaller than the full Source), keyed by type.
|
|
14
|
+
const ELEMENT_SCHEMAS = {};
|
|
15
|
+
{
|
|
16
|
+
const union = elementSchema;
|
|
17
|
+
const opts = union._def?.options ?? union.options ?? [];
|
|
18
|
+
for (const opt of opts) {
|
|
19
|
+
const shape = opt.shape;
|
|
20
|
+
const typeLit = shape?.type?._def?.value ?? shape?.type?.value;
|
|
21
|
+
if (typeof typeLit === 'string') {
|
|
22
|
+
ELEMENT_SCHEMAS[typeLit] = JSON.stringify(zodToJsonSchema(opt, { name: `${typeLit}Element`, $refStrategy: 'relative' }));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function elementSchemaJson(type) {
|
|
27
|
+
return ELEMENT_SCHEMAS[type] ?? null;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=schema-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-json.js","sourceRoot":"","sources":["../src/schema-json.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,iFAAiF;AACjF,kFAAkF;AAClF,mFAAmF;AACnF,EAAE;AACF,iFAAiF;AAEjF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,qFAAqF;AACrF,+EAA+E;AAC/E,iFAAiF;AACjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAC9C,eAAe,CAAC,YAA0B,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CACjG,CAAC;AAEF,+EAA+E;AAC/E,MAAM,eAAe,GAA2B,EAAE,CAAC;AACnD,CAAC;IACC,MAAM,KAAK,GAAG,aAAwE,CAAC;IACvF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;IACxD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAI,GAAmF,CAAC,KAAK,CAAC;QACzG,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;QAC/D,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,eAAe,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CACvC,eAAe,CAAC,GAAiB,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAC5F,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../src/server-config.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW;;;CAAwC,CAAC;AAEjE,eAAO,MAAM,mBAAmB;;;CAA+B,CAAC;AAEhE,eAAO,MAAM,mBAAmB,QA0BiE,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Shared server identity, capabilities, and agent instructions — used by BOTH
|
|
2
|
+
// entry points (the stdio bin in index.ts and a hosted HTTP route) so a remote
|
|
3
|
+
// server guides agents identically to the local one. Kept separate from
|
|
4
|
+
// index.ts so the library entry can import these without the stdio bootstrap.
|
|
5
|
+
export const SERVER_INFO = { name: 'clipkit', version: '0.0.0' };
|
|
6
|
+
export const SERVER_CAPABILITIES = { tools: {}, resources: {} };
|
|
7
|
+
export const SERVER_INSTRUCTIONS = 'Clipkit MCP — author Clipkit Protocol videos via tools, and read the canonical ' +
|
|
8
|
+
'authoring docs as resources. ' +
|
|
9
|
+
'BEFORE composing, call read_docs for the authoring guide (read_docs topic:"protocol" for ' +
|
|
10
|
+
'field semantics, topic:"brand" for brand-correct visuals). For exact field names + types ' +
|
|
11
|
+
'call get_schema (optionally with an element_type). These are TOOLS, not resources, so you ' +
|
|
12
|
+
'can read them directly. ' +
|
|
13
|
+
'TWO WAYS TO BUILD — pick by the brief, do NOT default to one: ' +
|
|
14
|
+
'(A) AUTHOR IT YOURSELF — write a full source JSON and call set_project. This is the full ' +
|
|
15
|
+
'creative canvas: every element type (text, image, video, shape, audio, group, caption, ' +
|
|
16
|
+
'particles) plus effects, 3D camera, lighting, gradients, keyframe animation, and ' +
|
|
17
|
+
'expressions. Use this for anything specific, original, or not a stock promo — most briefs. ' +
|
|
18
|
+
'(B) create_promo — a FAST path that assembles a conventional promo/intro/product/data ' +
|
|
19
|
+
'video from prebuilt scenes (it handles camera/glass/lighting/motion/layout). Good when a ' +
|
|
20
|
+
'template fits; it is ONE option, not the default. Mix scene types and fit the structure to ' +
|
|
21
|
+
'the content — do NOT reflexively make a glass-orb hero + CTA. ' +
|
|
22
|
+
'TWEAK an existing project with add_element / edit_element / delete_element. ' +
|
|
23
|
+
'SEE YOUR WORK — you cannot otherwise see the video: call preview_still for a frame, and ' +
|
|
24
|
+
'validate_project / describe_project for a structural read-back with render-time warnings. ' +
|
|
25
|
+
'The loop is edit → preview_still → fix. ' +
|
|
26
|
+
'CAPTIONS: transcribe_to_captions turns a media url (or local file) into a timed caption. ' +
|
|
27
|
+
'DELIVER: open_in_editor returns a free editor link; load_project re-imports a shared ' +
|
|
28
|
+
'project by id/URL; render_video renders a finished MP4 in the cloud (paid; needs ' +
|
|
29
|
+
'CLIPKIT_API_KEY). ' +
|
|
30
|
+
'PROJECT IDS: create_project / set_project / create_promo / load_project return a ' +
|
|
31
|
+
'project_id; pass it to subsequent tools (get_project / edit_element / preview_still / ' +
|
|
32
|
+
'validate_project / render_video / …). When working on a single local project you may omit it.';
|
|
33
|
+
//# sourceMappingURL=server-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../src/server-config.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,+EAA+E;AAC/E,wEAAwE;AACxE,8EAA8E;AAE9E,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAEjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAEhE,MAAM,CAAC,MAAM,mBAAmB,GAC9B,iFAAiF;IACjF,+BAA+B;IAC/B,2FAA2F;IAC3F,2FAA2F;IAC3F,4FAA4F;IAC5F,0BAA0B;IAC1B,gEAAgE;IAChE,2FAA2F;IAC3F,yFAAyF;IACzF,mFAAmF;IACnF,6FAA6F;IAC7F,wFAAwF;IACxF,2FAA2F;IAC3F,6FAA6F;IAC7F,gEAAgE;IAChE,8EAA8E;IAC9E,0FAA0F;IAC1F,4FAA4F;IAC5F,0CAA0C;IAC1C,2FAA2F;IAC3F,uFAAuF;IACvF,mFAAmF;IACnF,oBAAoB;IACpB,mFAAmF;IACnF,wFAAwF;IACxF,+FAA+F,CAAC"}
|
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Source } from '@clipkit/protocol';
|
|
2
|
+
/** A fresh, empty project. */
|
|
3
|
+
export declare function blankSource(): Source;
|
|
4
|
+
/** Deep-clone a Source so a tool can mutate a trial copy before validating. */
|
|
5
|
+
export declare function cloneSource(source: Source): Source;
|
|
6
|
+
export interface ElementLocation {
|
|
7
|
+
/** The matched element, as a mutable record. */
|
|
8
|
+
element: Record<string, unknown>;
|
|
9
|
+
/** The array that holds it — top-level, a group's `elements`, or a mask's. */
|
|
10
|
+
container: unknown[];
|
|
11
|
+
/** Its index within `container`. */
|
|
12
|
+
index: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Find an element by id ANYWHERE in the tree — top-level, nested `group`
|
|
16
|
+
* children, or `group.mask` children — returning the array that holds it and
|
|
17
|
+
* the index, so callers can edit or splice it in place. Returns null if absent.
|
|
18
|
+
*/
|
|
19
|
+
export declare function locateElement(elements: unknown[], id: string): ElementLocation | null;
|
|
20
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,8BAA8B;AAC9B,wBAAgB,WAAW,IAAI,MAAM,CASpC;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,8EAA8E;IAC9E,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAiBrF"}
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Source-manipulation helpers shared by the MCP tools.
|
|
2
|
+
//
|
|
3
|
+
// A "project" is just a Clipkit `Source`. Tools never own a Source directly;
|
|
4
|
+
// they go through a ProjectStore (see project-store.ts) so the same tool code
|
|
5
|
+
// works two ways: a single in-memory project over local stdio, or many
|
|
6
|
+
// concurrent projects in a shared DB behind a hosted, sessionless HTTP server.
|
|
7
|
+
/** A fresh, empty project. */
|
|
8
|
+
export function blankSource() {
|
|
9
|
+
return {
|
|
10
|
+
output_format: 'mp4',
|
|
11
|
+
width: 1920,
|
|
12
|
+
height: 1080,
|
|
13
|
+
duration: 10,
|
|
14
|
+
frame_rate: 30,
|
|
15
|
+
elements: [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Deep-clone a Source so a tool can mutate a trial copy before validating. */
|
|
19
|
+
export function cloneSource(source) {
|
|
20
|
+
return JSON.parse(JSON.stringify(source));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Find an element by id ANYWHERE in the tree — top-level, nested `group`
|
|
24
|
+
* children, or `group.mask` children — returning the array that holds it and
|
|
25
|
+
* the index, so callers can edit or splice it in place. Returns null if absent.
|
|
26
|
+
*/
|
|
27
|
+
export function locateElement(elements, id) {
|
|
28
|
+
for (let i = 0; i < elements.length; i++) {
|
|
29
|
+
const el = elements[i];
|
|
30
|
+
if (!el || typeof el !== 'object')
|
|
31
|
+
continue;
|
|
32
|
+
const rec = el;
|
|
33
|
+
if (rec.id === id)
|
|
34
|
+
return { element: rec, container: elements, index: i };
|
|
35
|
+
if (Array.isArray(rec.elements)) {
|
|
36
|
+
const hit = locateElement(rec.elements, id);
|
|
37
|
+
if (hit)
|
|
38
|
+
return hit;
|
|
39
|
+
}
|
|
40
|
+
const mask = rec.mask;
|
|
41
|
+
if (mask && Array.isArray(mask.elements)) {
|
|
42
|
+
const hit = locateElement(mask.elements, id);
|
|
43
|
+
if (hit)
|
|
44
|
+
return hit;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,uEAAuE;AACvE,+EAA+E;AAI/E,8BAA8B;AAC9B,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,aAAa,EAAE,KAAK;QACpB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,EAAE;KACb,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAW,CAAC;AACtD,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,QAAmB,EAAE,EAAU;IAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;YAAE,SAAS;QAC5C,MAAM,GAAG,GAAG,EAA6B,CAAC;QAC1C,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC1E,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC5C,IAAI,GAAG;gBAAE,OAAO,GAAG,CAAC;QACtB,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAA0C,CAAC;QAC5D,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC7C,IAAI,GAAG;gBAAE,OAAO,GAAG,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { type ProjectStore } from './project-store.js';
|
|
3
|
+
/**
|
|
4
|
+
* Register the Clipkit tools on `server`.
|
|
5
|
+
*
|
|
6
|
+
* `options.localTranscription` (default true) gates `transcribe_to_captions`,
|
|
7
|
+
* which runs Whisper in a child process and needs ffmpeg + a writable FS. Hosts
|
|
8
|
+
* that can't provide those — the hosted /mcp route on serverless — pass `false`
|
|
9
|
+
* so the tool isn't advertised where it would always fail. (A hosted STT path,
|
|
10
|
+
* via render-service or a hosted endpoint, is a TODO — figure out later.)
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerTools(server: McpServer, store: ProjectStore, options?: {
|
|
13
|
+
localTranscription?: boolean;
|
|
14
|
+
}): void;
|
|
15
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkBzE,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAqSpE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7C,IAAI,CA09BN"}
|