@autopo/mcp 0.0.0-stage → 0.1.1
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 +21 -0
- package/README.md +119 -2
- package/dist/api.d.ts +51 -0
- package/dist/api.js +107 -0
- package/dist/api.js.map +1 -0
- package/dist/apps.d.ts +10 -0
- package/dist/apps.js +146 -0
- package/dist/apps.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +63 -0
- package/dist/cli.js.map +1 -0
- package/dist/guides.d.ts +3 -0
- package/dist/guides.js +52 -0
- package/dist/guides.js.map +1 -0
- package/dist/http.d.ts +20 -0
- package/dist/http.js +119 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/kit.d.ts +149 -0
- package/dist/kit.js +206 -0
- package/dist/kit.js.map +1 -0
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.js +44 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +4 -0
- package/dist/resources.js +40 -0
- package/dist/resources.js.map +1 -0
- package/dist/server.d.ts +24 -0
- package/dist/server.js +40 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/company.d.ts +4 -0
- package/dist/tools/company.js +431 -0
- package/dist/tools/company.js.map +1 -0
- package/dist/tools/marketing.d.ts +4 -0
- package/dist/tools/marketing.js +214 -0
- package/dist/tools/marketing.js.map +1 -0
- package/dist/tools/studio.d.ts +9 -0
- package/dist/tools/studio.js +363 -0
- package/dist/tools/studio.js.map +1 -0
- package/dist/ui/gallery.html +124 -0
- package/dist/ui/home.html +124 -0
- package/dist/ui/inbox.html +124 -0
- package/dist/ui/money.html +124 -0
- package/dist/ui/storyboard.html +124 -0
- package/package.json +71 -4
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hosted server: Streamable HTTP, one person per request (their bearer token), two legs behind one path:
|
|
3
|
+
* - 2026-07-28 clients are served statelessly by createMcpHandler (any replica, no affinity);
|
|
4
|
+
* - 2025-era clients (today's Claude Code, Codex, Cursor) get a session-aware transport, because that is the only way
|
|
5
|
+
* their elicitation dialogs (confirmations, the company picker) can reach them over HTTP. Sessions die after idling.
|
|
6
|
+
*/
|
|
7
|
+
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
8
|
+
export interface HttpOptions {
|
|
9
|
+
port: number;
|
|
10
|
+
host: string;
|
|
11
|
+
apiUrl: string;
|
|
12
|
+
appUrl: string;
|
|
13
|
+
publicUrl?: string;
|
|
14
|
+
mediaDomains: string[];
|
|
15
|
+
/** Hostnames this server answers for; empty: any (a public service behind its own DNS). */
|
|
16
|
+
allowedHosts?: string[];
|
|
17
|
+
/** Seconds a 2025-era session may idle before it is closed. */
|
|
18
|
+
sessionIdleSeconds?: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function serveHttp(options: HttpOptions): import("node:http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hosted server: Streamable HTTP, one person per request (their bearer token), two legs behind one path:
|
|
3
|
+
* - 2026-07-28 clients are served statelessly by createMcpHandler (any replica, no affinity);
|
|
4
|
+
* - 2025-era clients (today's Claude Code, Codex, Cursor) get a session-aware transport, because that is the only way
|
|
5
|
+
* their elicitation dialogs (confirmations, the company picker) can reach them over HTTP. Sessions die after idling.
|
|
6
|
+
*/
|
|
7
|
+
import { createServer as createHttpServer } from 'node:http';
|
|
8
|
+
import { randomUUID, createHash } from 'node:crypto';
|
|
9
|
+
import { createMcpHandler, isLegacyRequest } from '@modelcontextprotocol/server';
|
|
10
|
+
import { NodeStreamableHTTPServerTransport, toNodeHandler, toWebRequest } from '@modelcontextprotocol/node';
|
|
11
|
+
import { createServer, VERSION } from './server.js';
|
|
12
|
+
const bearer = (req) => {
|
|
13
|
+
const header = req.headers.authorization ?? '';
|
|
14
|
+
const match = /^Bearer\s+(.+)$/i.exec(header.trim());
|
|
15
|
+
return match ? match[1].trim() : null;
|
|
16
|
+
};
|
|
17
|
+
const fingerprint = (token) => createHash('sha256').update(token).digest('hex').slice(0, 16);
|
|
18
|
+
function json(res, status, body, headers = {}) {
|
|
19
|
+
res.writeHead(status, { 'content-type': 'application/json', ...headers });
|
|
20
|
+
res.end(JSON.stringify(body));
|
|
21
|
+
}
|
|
22
|
+
async function readBody(req) {
|
|
23
|
+
const chunks = [];
|
|
24
|
+
for await (const chunk of req)
|
|
25
|
+
chunks.push(chunk);
|
|
26
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
27
|
+
if (!text)
|
|
28
|
+
return undefined;
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(text);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function serveHttp(options) {
|
|
37
|
+
const idleMs = (options.sessionIdleSeconds ?? 1800) * 1000;
|
|
38
|
+
const make = (token) => createServer({ token, apiUrl: options.apiUrl, appUrl: options.appUrl, mediaDomains: options.mediaDomains, ...(options.publicUrl ? { publicUrl: options.publicUrl } : {}) });
|
|
39
|
+
// modern leg: stateless, a fresh server per request from the caller's token
|
|
40
|
+
const modern = createMcpHandler((ctx) => make(ctx.authInfo?.token ?? ''), { legacy: 'reject', onerror: (e) => console.error('[mcp]', e.message) });
|
|
41
|
+
const modernNode = toNodeHandler(modern, { onerror: (e) => console.error('[mcp]', e.message) });
|
|
42
|
+
const sessions = new Map();
|
|
43
|
+
const sweep = setInterval(() => {
|
|
44
|
+
const cutoff = Date.now() - idleMs;
|
|
45
|
+
for (const [id, live] of sessions)
|
|
46
|
+
if (live.last < cutoff) {
|
|
47
|
+
sessions.delete(id);
|
|
48
|
+
void live.transport.close();
|
|
49
|
+
}
|
|
50
|
+
}, 60_000);
|
|
51
|
+
sweep.unref();
|
|
52
|
+
async function legacy(req, res, token, body) {
|
|
53
|
+
const sid = typeof req.headers['mcp-session-id'] === 'string' ? req.headers['mcp-session-id'] : undefined;
|
|
54
|
+
if (sid) {
|
|
55
|
+
const live = sessions.get(sid);
|
|
56
|
+
if (!live)
|
|
57
|
+
return json(res, 404, { jsonrpc: '2.0', error: { code: -32001, message: 'Session not found: start again.' }, id: null });
|
|
58
|
+
if (live.token !== token)
|
|
59
|
+
return json(res, 403, { error: { code: 'forbidden', message: 'This session belongs to another token.' } });
|
|
60
|
+
live.last = Date.now();
|
|
61
|
+
await live.transport.handleRequest(req, res, body);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (req.method !== 'POST')
|
|
65
|
+
return json(res, 400, { error: { code: 'bad_request', message: 'Open a session with an initialize request first.' } });
|
|
66
|
+
const transport = new NodeStreamableHTTPServerTransport({
|
|
67
|
+
sessionIdGenerator: () => randomUUID(),
|
|
68
|
+
onsessioninitialized: (id) => { sessions.set(id, { transport, token, last: Date.now() }); },
|
|
69
|
+
onsessionclosed: (id) => { sessions.delete(id); },
|
|
70
|
+
});
|
|
71
|
+
transport.onclose = () => { if (transport.sessionId)
|
|
72
|
+
sessions.delete(transport.sessionId); };
|
|
73
|
+
const server = make(token);
|
|
74
|
+
await server.connect(transport);
|
|
75
|
+
await transport.handleRequest(req, res, body);
|
|
76
|
+
}
|
|
77
|
+
const httpServer = createHttpServer(async (req, res) => {
|
|
78
|
+
try {
|
|
79
|
+
const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
|
|
80
|
+
if (options.allowedHosts?.length) {
|
|
81
|
+
const host = (req.headers.host ?? '').split(':')[0];
|
|
82
|
+
if (!options.allowedHosts.includes(host ?? ''))
|
|
83
|
+
return json(res, 403, { error: { code: 'forbidden', message: 'Unknown host.' } });
|
|
84
|
+
}
|
|
85
|
+
if (url.pathname === '/healthz')
|
|
86
|
+
return json(res, 200, { ok: true, version: VERSION });
|
|
87
|
+
if (url.pathname === '/' && req.method === 'GET') {
|
|
88
|
+
return json(res, 200, { name: 'autopoiesis', version: VERSION, mcp: '/mcp', docs: 'https://docs.autopoiesis.app', hint: 'POST JSON-RPC to /mcp with Authorization: Bearer apk_…' });
|
|
89
|
+
}
|
|
90
|
+
if (url.pathname !== '/mcp' && url.pathname !== '/mcp/')
|
|
91
|
+
return json(res, 404, { error: { code: 'not_found', message: 'The MCP endpoint is /mcp.' } });
|
|
92
|
+
const token = bearer(req);
|
|
93
|
+
if (!token) {
|
|
94
|
+
return json(res, 401, { error: { code: 'not_authenticated', message: 'Send Authorization: Bearer <your token>. Make one in the app: Connectors → MCP.' } }, { 'www-authenticate': 'Bearer realm="autopoiesis", error="invalid_token"' });
|
|
95
|
+
}
|
|
96
|
+
const body = req.method === 'POST' ? await readBody(req) : undefined;
|
|
97
|
+
const authInfo = { token, clientId: fingerprint(token), scopes: [] };
|
|
98
|
+
req.auth = authInfo;
|
|
99
|
+
const web = await toWebRequest(req, body);
|
|
100
|
+
if (await isLegacyRequest(web, body))
|
|
101
|
+
return legacy(req, res, token, body);
|
|
102
|
+
await modernNode(req, res, body);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error('[mcp]', error.message);
|
|
106
|
+
if (!res.headersSent)
|
|
107
|
+
json(res, 500, { error: { code: 'internal', message: 'The server could not handle that request.' } });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
httpServer.listen(options.port, options.host, () => {
|
|
111
|
+
console.error(`autopoiesis-mcp ${VERSION} on http://${options.host}:${options.port}/mcp → ${options.apiUrl}`);
|
|
112
|
+
});
|
|
113
|
+
const stop = () => { clearInterval(sweep); httpServer.close(); void modern.close(); for (const live of sessions.values())
|
|
114
|
+
void live.transport.close(); process.exit(0); };
|
|
115
|
+
process.on('SIGINT', stop);
|
|
116
|
+
process.on('SIGTERM', stop);
|
|
117
|
+
return httpServer;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createServer, DEFAULT_API_URL, DEFAULT_APP_URL, INSTRUCTIONS, VERSION } from './server.js';
|
|
2
|
+
export { Api, ApiError } from './api.js';
|
|
3
|
+
export { CATALOG, Session } from './kit.js';
|
|
4
|
+
export { VIEWS, viewUri } from './apps.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,OAAO,EAAsB,MAAM,aAAa,CAAA;AACvH,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAgB,MAAM,UAAU,CAAA;AACzD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA"}
|
package/dist/kit.d.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every tool shares: the person's session (their API, the companies they are in, a small cache), the company a
|
|
3
|
+
* call is about (asked for with an elicitation form when they have several), confirmations before anything that spends
|
|
4
|
+
* credits or cannot be undone (also elicitation, so the host shows a real dialog instead of trusting the model to ask),
|
|
5
|
+
* and the `define()` wrapper that turns a plain handler into an MCP tool with text + structured results and clean errors.
|
|
6
|
+
*/
|
|
7
|
+
import type { CallToolResult, InputRequiredResult, McpServer, ServerContext, ToolAnnotations } from '@modelcontextprotocol/server';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { Api } from './api.js';
|
|
10
|
+
export declare class ToolError extends Error {
|
|
11
|
+
}
|
|
12
|
+
export interface Company {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
kind?: string;
|
|
16
|
+
stage?: string;
|
|
17
|
+
status?: string;
|
|
18
|
+
role?: string;
|
|
19
|
+
tagline?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface StudioModel {
|
|
22
|
+
key: string;
|
|
23
|
+
kind: string;
|
|
24
|
+
label?: string;
|
|
25
|
+
cents?: number;
|
|
26
|
+
unit?: string;
|
|
27
|
+
available?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface SessionOptions {
|
|
30
|
+
api: Api;
|
|
31
|
+
/** The web app's origin, for "open in the app" links. */
|
|
32
|
+
appUrl: string;
|
|
33
|
+
/** Hosts the App views may load media from (CSP resourceDomains), beyond the API itself. */
|
|
34
|
+
mediaDomains?: string[];
|
|
35
|
+
/** The public address of this server when it is hosted (for the Claude sandbox domain). */
|
|
36
|
+
publicUrl?: string;
|
|
37
|
+
}
|
|
38
|
+
/** One person's connection: their API plus a short-lived cache of what tools keep asking for. */
|
|
39
|
+
export declare class Session {
|
|
40
|
+
readonly api: Api;
|
|
41
|
+
readonly appUrl: string;
|
|
42
|
+
readonly mediaDomains: string[];
|
|
43
|
+
readonly publicUrl: string | undefined;
|
|
44
|
+
private companiesCache;
|
|
45
|
+
private studioCache;
|
|
46
|
+
private schemaCache;
|
|
47
|
+
constructor(options: SessionOptions);
|
|
48
|
+
companies(): Promise<Company[]>;
|
|
49
|
+
/** The Studio's models and defaults for a company, to say what a generation will cost before it is made. */
|
|
50
|
+
studio(companyId: string): Promise<{
|
|
51
|
+
at: number;
|
|
52
|
+
models: StudioModel[];
|
|
53
|
+
defaults: Record<string, string>;
|
|
54
|
+
}>;
|
|
55
|
+
/** The API's OpenAPI document (public), the manual behind `api_request`. */
|
|
56
|
+
schema(): Promise<Record<string, unknown>>;
|
|
57
|
+
link(path: string): string;
|
|
58
|
+
}
|
|
59
|
+
export interface Choice {
|
|
60
|
+
value: string;
|
|
61
|
+
label: string;
|
|
62
|
+
}
|
|
63
|
+
/** A single-choice field, titled options (the host shows the labels, we get the value back). */
|
|
64
|
+
export declare function choice(title: string, options: Choice[], description?: string): {
|
|
65
|
+
type: 'string';
|
|
66
|
+
title: string;
|
|
67
|
+
description?: string;
|
|
68
|
+
oneOf: {
|
|
69
|
+
const: string;
|
|
70
|
+
title: string;
|
|
71
|
+
}[];
|
|
72
|
+
};
|
|
73
|
+
export declare function textField(title: string, description?: string, opts?: {
|
|
74
|
+
maxLength?: number;
|
|
75
|
+
required?: boolean;
|
|
76
|
+
}): {
|
|
77
|
+
type: 'string';
|
|
78
|
+
title: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
maxLength?: number;
|
|
81
|
+
};
|
|
82
|
+
export declare function boolField(title: string, description?: string, defaultValue?: boolean): {
|
|
83
|
+
type: 'boolean';
|
|
84
|
+
title: string;
|
|
85
|
+
description?: string;
|
|
86
|
+
default?: boolean;
|
|
87
|
+
};
|
|
88
|
+
type FieldSchema = ReturnType<typeof choice> | ReturnType<typeof textField> | ReturnType<typeof boolField>;
|
|
89
|
+
/** Ask the person something through the host's dialog. `key` names the answer on the retry. */
|
|
90
|
+
export declare function ask(key: string, message: string, fields: Record<string, FieldSchema>, required?: string[]): InputRequiredResult;
|
|
91
|
+
/** Ask the person to open a link (sign-in, checkout, a page of the app) in their browser. */
|
|
92
|
+
export declare function askToOpen(key: string, url: string, message: string): InputRequiredResult;
|
|
93
|
+
/** What came back for `key` on a retry: the accepted content, `null` when declined or cancelled, `undefined` when not asked yet. */
|
|
94
|
+
export declare function answer<T extends Record<string, unknown> = Record<string, unknown>>(ctx: ServerContext, key: string): T | null | undefined;
|
|
95
|
+
/** A yes/no confirmation, as a real choice so hosts that auto-accept empty forms still show it. */
|
|
96
|
+
export declare function confirm(ctx: ServerContext, key: string, message: string, yes?: string, no?: string): true | CallToolResult | InputRequiredResult;
|
|
97
|
+
/** Resolve the company a call is about: the one named, else the only one, else ask (an elicitation form). */
|
|
98
|
+
export declare function resolveCompany(s: Session, args: {
|
|
99
|
+
company?: string | undefined;
|
|
100
|
+
}, ctx: ServerContext): Promise<string | InputRequiredResult>;
|
|
101
|
+
export declare const isInputRequired: (v: unknown) => v is InputRequiredResult;
|
|
102
|
+
export declare function text(message: string, extra?: Record<string, unknown>): CallToolResult;
|
|
103
|
+
export declare function failure(message: string): CallToolResult;
|
|
104
|
+
/** Money for people: cents → "$1.20". */
|
|
105
|
+
export declare function money(cents: number | null | undefined): string;
|
|
106
|
+
export type Group = 'company' | 'briefings' | 'inbox' | 'tasks' | 'team' | 'runs' | 'knowledge' | 'studio' | 'marketing' | 'money' | 'api';
|
|
107
|
+
export declare const COMPANY_ARG: {
|
|
108
|
+
company: z.ZodOptional<z.ZodString>;
|
|
109
|
+
};
|
|
110
|
+
export declare const PAGE_ARGS: {
|
|
111
|
+
page: z.ZodOptional<z.ZodNumber>;
|
|
112
|
+
page_size: z.ZodOptional<z.ZodNumber>;
|
|
113
|
+
};
|
|
114
|
+
export interface ToolSpec<Shape extends z.ZodRawShape> {
|
|
115
|
+
title?: string;
|
|
116
|
+
description: string;
|
|
117
|
+
input?: Shape;
|
|
118
|
+
group: Group;
|
|
119
|
+
/** read: readOnlyHint; write: a change; spend: credits leave; destructive: cannot be undone. */
|
|
120
|
+
kind?: 'read' | 'write' | 'spend' | 'destructive';
|
|
121
|
+
/** The App view (ui://…) a host may show for this tool's result. */
|
|
122
|
+
ui?: string;
|
|
123
|
+
icons?: {
|
|
124
|
+
src: string;
|
|
125
|
+
mimeType?: string;
|
|
126
|
+
sizes?: string[];
|
|
127
|
+
}[];
|
|
128
|
+
}
|
|
129
|
+
export type Handler<Shape extends z.ZodRawShape> = (args: z.infer<z.ZodObject<Shape>>, ctx: ServerContext, s: Session) => Promise<unknown>;
|
|
130
|
+
export interface ToolDoc {
|
|
131
|
+
name: string;
|
|
132
|
+
title?: string;
|
|
133
|
+
group: Group;
|
|
134
|
+
kind: 'read' | 'write' | 'spend' | 'destructive';
|
|
135
|
+
description: string;
|
|
136
|
+
inputSchema: Record<string, unknown>;
|
|
137
|
+
ui?: string;
|
|
138
|
+
}
|
|
139
|
+
/** Every tool the server defines, in order, for the docs generator and tests. */
|
|
140
|
+
export declare const CATALOG: ToolDoc[];
|
|
141
|
+
export declare function annotationsFor(kind: NonNullable<ToolSpec<z.ZodRawShape>['kind']>, title?: string): ToolAnnotations;
|
|
142
|
+
export declare function metaFor(kind: NonNullable<ToolSpec<z.ZodRawShape>['kind']>, ui?: string): Record<string, unknown>;
|
|
143
|
+
/**
|
|
144
|
+
* Define a tool: `handler` returns plain JSON (sent as text and as structuredContent), a `CallToolResult`, or an
|
|
145
|
+
* elicitation (`ask`/`confirm`/`askToOpen`). API failures and ToolErrors come back as `isError` results, never as
|
|
146
|
+
* protocol errors, so the model can read them and carry on.
|
|
147
|
+
*/
|
|
148
|
+
export declare function define<Shape extends z.ZodRawShape>(server: McpServer, s: Session, name: string, spec: ToolSpec<Shape>, handler: Handler<Shape>): void;
|
|
149
|
+
export {};
|
package/dist/kit.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { inputRequired } from '@modelcontextprotocol/server';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ApiError, rows } from './api.js';
|
|
4
|
+
export class ToolError extends Error {
|
|
5
|
+
}
|
|
6
|
+
/** One person's connection: their API plus a short-lived cache of what tools keep asking for. */
|
|
7
|
+
export class Session {
|
|
8
|
+
api;
|
|
9
|
+
appUrl;
|
|
10
|
+
mediaDomains;
|
|
11
|
+
publicUrl;
|
|
12
|
+
companiesCache = null;
|
|
13
|
+
studioCache = new Map();
|
|
14
|
+
schemaCache = null;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.api = options.api;
|
|
17
|
+
this.appUrl = options.appUrl.replace(/\/+$/, '');
|
|
18
|
+
this.mediaDomains = options.mediaDomains ?? [];
|
|
19
|
+
this.publicUrl = options.publicUrl;
|
|
20
|
+
}
|
|
21
|
+
async companies() {
|
|
22
|
+
if (this.companiesCache && Date.now() - this.companiesCache.at < 60_000)
|
|
23
|
+
return this.companiesCache.rows;
|
|
24
|
+
const list = rows(await this.api.get('/api/companies'));
|
|
25
|
+
this.companiesCache = { at: Date.now(), rows: list };
|
|
26
|
+
return list;
|
|
27
|
+
}
|
|
28
|
+
/** The Studio's models and defaults for a company, to say what a generation will cost before it is made. */
|
|
29
|
+
async studio(companyId) {
|
|
30
|
+
const hit = this.studioCache.get(companyId);
|
|
31
|
+
if (hit && Date.now() - hit.at < 300_000)
|
|
32
|
+
return hit;
|
|
33
|
+
try {
|
|
34
|
+
const data = (await this.api.get(`/api/companies/${companyId}/studio`));
|
|
35
|
+
const entry = { at: Date.now(), models: data.models ?? [], defaults: data.defaults ?? {} };
|
|
36
|
+
this.studioCache.set(companyId, entry);
|
|
37
|
+
return entry;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return { at: Date.now(), models: [], defaults: {} };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** The API's OpenAPI document (public), the manual behind `api_request`. */
|
|
44
|
+
async schema() {
|
|
45
|
+
if (this.schemaCache && Date.now() - this.schemaCache.at < 3_600_000)
|
|
46
|
+
return this.schemaCache.schema;
|
|
47
|
+
const schema = (await this.api.get('/api/schema/', { format: 'json' }));
|
|
48
|
+
this.schemaCache = { at: Date.now(), schema };
|
|
49
|
+
return schema;
|
|
50
|
+
}
|
|
51
|
+
link(path) {
|
|
52
|
+
return `${this.appUrl}${path.startsWith('/') ? path : `/${path}`}`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** A single-choice field, titled options (the host shows the labels, we get the value back). */
|
|
56
|
+
export function choice(title, options, description) {
|
|
57
|
+
return { type: 'string', title, ...(description ? { description } : {}), oneOf: options.map((o) => ({ const: o.value, title: o.label })) };
|
|
58
|
+
}
|
|
59
|
+
export function textField(title, description, opts = {}) {
|
|
60
|
+
return { type: 'string', title, ...(description ? { description } : {}), ...(opts.maxLength ? { maxLength: opts.maxLength } : {}) };
|
|
61
|
+
}
|
|
62
|
+
export function boolField(title, description, defaultValue) {
|
|
63
|
+
return { type: 'boolean', title, ...(description ? { description } : {}), ...(defaultValue !== undefined ? { default: defaultValue } : {}) };
|
|
64
|
+
}
|
|
65
|
+
/** Ask the person something through the host's dialog. `key` names the answer on the retry. */
|
|
66
|
+
export function ask(key, message, fields, required = Object.keys(fields)) {
|
|
67
|
+
return inputRequired({
|
|
68
|
+
inputRequests: {
|
|
69
|
+
[key]: inputRequired.elicit({
|
|
70
|
+
message,
|
|
71
|
+
requestedSchema: { type: 'object', properties: fields, required },
|
|
72
|
+
}),
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/** Ask the person to open a link (sign-in, checkout, a page of the app) in their browser. */
|
|
77
|
+
export function askToOpen(key, url, message) {
|
|
78
|
+
return inputRequired({ inputRequests: { [key]: inputRequired.elicitUrl({ url, message }) } });
|
|
79
|
+
}
|
|
80
|
+
/** What came back for `key` on a retry: the accepted content, `null` when declined or cancelled, `undefined` when not asked yet. */
|
|
81
|
+
export function answer(ctx, key) {
|
|
82
|
+
const raw = ctx.mcpReq.inputResponses?.[key];
|
|
83
|
+
if (!raw || typeof raw !== 'object')
|
|
84
|
+
return undefined;
|
|
85
|
+
if (raw.action === 'accept')
|
|
86
|
+
return (raw.content ?? {});
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/** A yes/no confirmation, as a real choice so hosts that auto-accept empty forms still show it. */
|
|
90
|
+
export function confirm(ctx, key, message, yes = 'Yes, go ahead', no = 'No, not now') {
|
|
91
|
+
const got = answer(ctx, key);
|
|
92
|
+
if (got === undefined)
|
|
93
|
+
return ask(key, message, { go: choice('Go ahead?', [{ value: 'yes', label: yes }, { value: 'no', label: no }]) });
|
|
94
|
+
if (got === null || got.go !== 'yes')
|
|
95
|
+
return text('Not done: you said no. Nothing changed and nothing was spent.');
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
/** Resolve the company a call is about: the one named, else the only one, else ask (an elicitation form). */
|
|
99
|
+
export async function resolveCompany(s, args, ctx) {
|
|
100
|
+
const given = (args.company ?? '').trim();
|
|
101
|
+
if (given)
|
|
102
|
+
return given;
|
|
103
|
+
const all = await s.companies();
|
|
104
|
+
const active = all.filter((c) => c.kind !== 'personal');
|
|
105
|
+
const options = active.length ? active : all;
|
|
106
|
+
if (options.length === 1)
|
|
107
|
+
return options[0].id;
|
|
108
|
+
if (options.length === 0)
|
|
109
|
+
throw new ToolError('You belong to no company yet. Create one in the app first.');
|
|
110
|
+
const picked = answer(ctx, 'company');
|
|
111
|
+
if (picked && picked.company && options.some((c) => c.id === picked.company))
|
|
112
|
+
return picked.company;
|
|
113
|
+
if (picked === null)
|
|
114
|
+
throw new ToolError('No company chosen. Say which company (list_companies) and try again.');
|
|
115
|
+
return ask('company', 'Which company is this about?', {
|
|
116
|
+
company: choice('Company', options.slice(0, 20).map((c) => ({ value: c.id, label: c.stage ? `${c.name} (${c.stage})` : c.name }))),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
export const isInputRequired = (v) => Boolean(v && typeof v === 'object' && v.resultType === 'input_required');
|
|
120
|
+
const isToolResult = (v) => Boolean(v && typeof v === 'object' && Array.isArray(v.content));
|
|
121
|
+
export function text(message, extra) {
|
|
122
|
+
return { content: [{ type: 'text', text: message }], structuredContent: { message, ...(extra ?? {}) } };
|
|
123
|
+
}
|
|
124
|
+
export function failure(message) {
|
|
125
|
+
return { isError: true, content: [{ type: 'text', text: message }] };
|
|
126
|
+
}
|
|
127
|
+
/** Money for people: cents → "$1.20". */
|
|
128
|
+
export function money(cents) {
|
|
129
|
+
if (cents === null || cents === undefined || Number.isNaN(cents))
|
|
130
|
+
return 'a few credits';
|
|
131
|
+
const dollars = cents / 100;
|
|
132
|
+
return dollars >= 10 ? `$${dollars.toFixed(0)}` : `$${dollars.toFixed(2)}`;
|
|
133
|
+
}
|
|
134
|
+
export const COMPANY_ARG = { company: z.string().optional().describe('the company id (list_companies); not needed when you have one company, asked for otherwise') };
|
|
135
|
+
export const PAGE_ARGS = {
|
|
136
|
+
page: z.number().int().min(1).optional(),
|
|
137
|
+
page_size: z.number().int().min(1).max(100).optional(),
|
|
138
|
+
};
|
|
139
|
+
/** Every tool the server defines, in order, for the docs generator and tests. */
|
|
140
|
+
export const CATALOG = [];
|
|
141
|
+
export function annotationsFor(kind, title) {
|
|
142
|
+
return {
|
|
143
|
+
...(title ? { title } : {}),
|
|
144
|
+
readOnlyHint: kind === 'read',
|
|
145
|
+
destructiveHint: kind === 'destructive',
|
|
146
|
+
idempotentHint: kind === 'read',
|
|
147
|
+
openWorldHint: false,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export function metaFor(kind, ui) {
|
|
151
|
+
const meta = {};
|
|
152
|
+
if (kind === 'spend' || kind === 'destructive') {
|
|
153
|
+
meta['anthropic/requiresUserInteraction'] = true; // Claude Code: always prompt, even in accept-all modes
|
|
154
|
+
meta['cursor/requiresConfirmation'] = true; // Cursor: an approval card before every call
|
|
155
|
+
}
|
|
156
|
+
if (ui)
|
|
157
|
+
meta.ui = { resourceUri: ui, visibility: ['model', 'app'] };
|
|
158
|
+
return meta;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Define a tool: `handler` returns plain JSON (sent as text and as structuredContent), a `CallToolResult`, or an
|
|
162
|
+
* elicitation (`ask`/`confirm`/`askToOpen`). API failures and ToolErrors come back as `isError` results, never as
|
|
163
|
+
* protocol errors, so the model can read them and carry on.
|
|
164
|
+
*/
|
|
165
|
+
export function define(server, s, name, spec, handler) {
|
|
166
|
+
const kind = spec.kind ?? 'read';
|
|
167
|
+
const shape = (spec.input ?? {});
|
|
168
|
+
const inputSchema = z.object(shape);
|
|
169
|
+
const config = {
|
|
170
|
+
...(spec.title ? { title: spec.title } : {}),
|
|
171
|
+
description: spec.description,
|
|
172
|
+
inputSchema,
|
|
173
|
+
outputSchema: z.looseObject({}),
|
|
174
|
+
annotations: annotationsFor(kind, spec.title),
|
|
175
|
+
_meta: metaFor(kind, spec.ui),
|
|
176
|
+
...(spec.icons ? { icons: spec.icons } : {}),
|
|
177
|
+
};
|
|
178
|
+
CATALOG.push({
|
|
179
|
+
name,
|
|
180
|
+
...(spec.title ? { title: spec.title } : {}),
|
|
181
|
+
group: spec.group,
|
|
182
|
+
kind,
|
|
183
|
+
description: spec.description,
|
|
184
|
+
inputSchema: z.toJSONSchema(inputSchema),
|
|
185
|
+
...(spec.ui ? { ui: spec.ui } : {}),
|
|
186
|
+
});
|
|
187
|
+
server.registerTool(name, config, (async (args, ctx) => {
|
|
188
|
+
try {
|
|
189
|
+
const result = await handler(args, ctx, s);
|
|
190
|
+
if (isInputRequired(result) || isToolResult(result))
|
|
191
|
+
return result;
|
|
192
|
+
const structured = result && typeof result === 'object' && !Array.isArray(result) ? result : { results: result };
|
|
193
|
+
return { content: [{ type: 'text', text: JSON.stringify(structured, null, 0) }], structuredContent: structured };
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
if (error instanceof ApiError) {
|
|
197
|
+
const code = error.code ? `, ${error.code}` : '';
|
|
198
|
+
return failure(`${error.message} (HTTP ${error.status}${code})`);
|
|
199
|
+
}
|
|
200
|
+
if (error instanceof ToolError)
|
|
201
|
+
return failure(error.message);
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=kit.js.map
|
package/dist/kit.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kit.js","sourceRoot":"","sources":["../src/kit.ts"],"names":[],"mappings":"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"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const where = (company) => (company ? ` (company ${company})` : '');
|
|
3
|
+
const user = (text) => ({ messages: [{ role: 'user', content: { type: 'text', text } }] });
|
|
4
|
+
export function registerPrompts(server) {
|
|
5
|
+
server.registerPrompt('morning_review', {
|
|
6
|
+
title: 'Morning review',
|
|
7
|
+
description: 'What happened in the company since yesterday: the briefing, what needs me, what is stuck.',
|
|
8
|
+
argsSchema: z.object({ company: z.string().optional().describe('the company id (optional with one company)') }),
|
|
9
|
+
}, ({ company }) => user(`Review my company${where(company)}. Call founder_home, then list_decisions (pending) and list_briefings. Tell me in a short briefing: what needs me (with the card ids), what the team delivered, what is stuck, and what you'd decide. Don't decide anything yourself: when I say so, use decide and I will confirm in the dialog.`));
|
|
10
|
+
server.registerPrompt('make_a_teaser', {
|
|
11
|
+
title: 'Make a teaser video',
|
|
12
|
+
description: 'Make a short teaser for the company in the Studio with the Creative Director, from one line, step by step.',
|
|
13
|
+
argsSchema: z.object({
|
|
14
|
+
idea: z.string().describe('what the teaser is for, in a sentence or two'),
|
|
15
|
+
seconds: z.string().optional().describe('length in seconds (default 20)'),
|
|
16
|
+
shape: z.string().optional().describe('16:9 (default), 9:16, 1:1 or 4:5'),
|
|
17
|
+
company: z.string().optional().describe('the company id (optional with one company)'),
|
|
18
|
+
}),
|
|
19
|
+
}, ({ idea, seconds, shape, company }) => user(`Make a ${seconds ?? '20'}-second ${shape ?? '16:9'} teaser${where(company)}: ${idea}\n\n` +
|
|
20
|
+
`Work in steps, telling me what you see after each one:\n` +
|
|
21
|
+
`1. brand_brain, so the teaser speaks like the company. Then create_video with a title and a brief written from the idea and the brand (who it's for, what it must show, the one thing to feel), seconds ${seconds ?? 20}.\n` +
|
|
22
|
+
`2. get_video and read the drafted shots back to me in one line each. Ask the Creative Director to tighten them: ask_agent creative, with production set to the video id, telling her the brief and what to change. Apply her proposals with apply_chat_action or set_video_shots.\n` +
|
|
23
|
+
`3. studio_overview to pick the models; set them with update_video {style: {models: {clip, keyframe, voice, music}}} only if the defaults don't fit the brief.\n` +
|
|
24
|
+
`4. video_keyframes (I confirm the cost in the dialog), then wait_for_video, then critique_video stage keyframes. Show me what the critic kept and ask if the look is right.\n` +
|
|
25
|
+
`5. make_video_media what all (I confirm), wait_for_video until nothing is generating, critique_video stage clips.\n` +
|
|
26
|
+
`6. render_video, wait_for_video, then give me the render link and open_in_app video so I can watch it. If anything is still missing, say what and stop.\n` +
|
|
27
|
+
`Never spend without the dialog, and keep each message short.`));
|
|
28
|
+
server.registerPrompt('decide_inbox', {
|
|
29
|
+
title: 'Decide the inbox',
|
|
30
|
+
description: 'Walk the pending cards one by one with a recommendation each; I decide, you call decide.',
|
|
31
|
+
argsSchema: z.object({ company: z.string().optional().describe('the company id (optional with one company)') }),
|
|
32
|
+
}, ({ company }) => user(`Walk me through the Board inbox${where(company)}: list_decisions pending, then for each card (get_decision when the summary is thin) tell me in three lines what the team wants, what it costs or risks, and what you would do. Wait for my answer per card, then call decide; I confirm in the dialog. Rejections need a note: ask me for one.`));
|
|
33
|
+
server.registerPrompt('studio_status', {
|
|
34
|
+
title: 'Studio status',
|
|
35
|
+
description: 'Every video in the Studio and where it stands.',
|
|
36
|
+
argsSchema: z.object({ company: z.string().optional().describe('the company id (optional with one company)') }),
|
|
37
|
+
}, ({ company }) => user(`List the Studio's videos${where(company)} (list_videos), open each that is not ready (get_video) and tell me what each one still needs, in one line a video.`));
|
|
38
|
+
server.registerPrompt('weekly_marketing', {
|
|
39
|
+
title: 'Weekly marketing',
|
|
40
|
+
description: 'What the company posted, what worked, and three posts for next week, checked against the brand before anything goes out.',
|
|
41
|
+
argsSchema: z.object({ company: z.string().optional().describe('the company id (optional with one company)') }),
|
|
42
|
+
}, ({ company }) => user(`Marketing week${where(company)}: brand_brain, list_posts (published), marketing_learnings. Tell me what worked in five lines. Then draft three posts for next week in the brand's voice, run check_posts on them, fix what the gate flags, and show me the final texts. Only when I say so, create_posts (I confirm in the dialog).`));
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** What a client can read as resources: the guides, a company's home and brand brain, the API's OpenAPI document. */
|
|
2
|
+
import { type McpServer } from '@modelcontextprotocol/server';
|
|
3
|
+
import type { Session } from './kit.js';
|
|
4
|
+
export declare function registerResources(server: McpServer, s: Session): void;
|