user-majico-mcp 0.7.5
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 +144 -0
- package/dist/agent-bootstrap.d.ts +8 -0
- package/dist/agent-bootstrap.js +21 -0
- package/dist/auth-prompt.d.ts +13 -0
- package/dist/auth-prompt.js +15 -0
- package/dist/client-disconnect.d.ts +4 -0
- package/dist/client-disconnect.js +17 -0
- package/dist/credentials.d.ts +40 -0
- package/dist/credentials.js +60 -0
- package/dist/http-handler.d.ts +6 -0
- package/dist/http-handler.js +28 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +22 -0
- package/dist/present-interactive.d.ts +92 -0
- package/dist/present-interactive.js +479 -0
- package/dist/present-types.d.ts +17 -0
- package/dist/present-types.js +1 -0
- package/dist/project-relevance.d.ts +27 -0
- package/dist/project-relevance.js +95 -0
- package/dist/project-selection-hints.d.ts +16 -0
- package/dist/project-selection-hints.js +32 -0
- package/dist/project-selection.d.ts +25 -0
- package/dist/project-selection.js +42 -0
- package/dist/recommended-external-skills.d.ts +39 -0
- package/dist/recommended-external-skills.js +319 -0
- package/dist/sdk-surface.d.ts +10 -0
- package/dist/sdk-surface.js +24 -0
- package/dist/server-branding.d.ts +17 -0
- package/dist/server-branding.js +40 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +24 -0
- package/dist/svg-preview-block.d.ts +14 -0
- package/dist/svg-preview-block.js +82 -0
- package/dist/tools/constants.d.ts +47 -0
- package/dist/tools/constants.js +95 -0
- package/dist/tools/dispatch-branding-studio.d.ts +5 -0
- package/dist/tools/dispatch-branding-studio.js +197 -0
- package/dist/tools/dispatch-pulse-blog.d.ts +3 -0
- package/dist/tools/dispatch-pulse-blog.js +158 -0
- package/dist/tools/dispatch-research-assets.d.ts +3 -0
- package/dist/tools/dispatch-research-assets.js +132 -0
- package/dist/tools/handle-tool-call-pre.d.ts +4 -0
- package/dist/tools/handle-tool-call-pre.js +47 -0
- package/dist/tools/handle-tool-call.d.ts +3 -0
- package/dist/tools/handle-tool-call.js +56 -0
- package/dist/tools/tool-call-helpers.d.ts +22 -0
- package/dist/tools/tool-call-helpers.js +104 -0
- package/dist/tools/tool-catalog.d.ts +14 -0
- package/dist/tools/tool-catalog.js +54 -0
- package/dist/tools/tool-definitions-blog-git.d.ts +2 -0
- package/dist/tools/tool-definitions-blog-git.js +207 -0
- package/dist/tools/tool-definitions-branding.d.ts +2 -0
- package/dist/tools/tool-definitions-branding.js +197 -0
- package/dist/tools/tool-definitions-research-aliases.d.ts +2 -0
- package/dist/tools/tool-definitions-research-aliases.js +340 -0
- package/dist/tools/tool-definitions-studio-pulse.d.ts +2 -0
- package/dist/tools/tool-definitions-studio-pulse.js +235 -0
- package/dist/tools/tool-matrix.d.ts +12 -0
- package/dist/tools/tool-matrix.js +36 -0
- package/dist/tools.d.ts +5 -0
- package/dist/tools.js +3 -0
- package/dist/ui-ux-skills.d.ts +33 -0
- package/dist/ui-ux-skills.js +157 -0
- package/dist/user-pick-policy.d.ts +18 -0
- package/dist/user-pick-policy.js +21 -0
- package/package.json +71 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { bootstrapProjectViaAgent } from "../agent-bootstrap.js";
|
|
2
|
+
import { buildUiUxSkillsHandoffPayload, renderUiUxSkillsHandoffMarkdown, } from "../ui-ux-skills.js";
|
|
3
|
+
import { buildMcpAuthRequiredPayload } from "../auth-prompt.js";
|
|
4
|
+
import { toolError, toolJson, buildStableBrandMarkdown, clientFromArgs, } from "./tool-call-helpers.js";
|
|
5
|
+
/** Pre-client tools and plan gate checks. */
|
|
6
|
+
export async function handlePreClientToolCall(name, args, defaultCredentials) {
|
|
7
|
+
if (name === "bootstrap_project") {
|
|
8
|
+
if (!defaultCredentials?.includeAdminTools) {
|
|
9
|
+
return toolError("bootstrap_project is admin-only. Use create_project or list_projects after OAuth login, or pass X-Majico-Agent-Secret for server automation.");
|
|
10
|
+
}
|
|
11
|
+
const projectName = args?.name;
|
|
12
|
+
if (!projectName?.trim())
|
|
13
|
+
return toolError("name is required.");
|
|
14
|
+
const { project } = await bootstrapProjectViaAgent(projectName.trim());
|
|
15
|
+
return toolJson(project);
|
|
16
|
+
}
|
|
17
|
+
if (name === "generate_brand_md") {
|
|
18
|
+
return buildStableBrandMarkdown(args);
|
|
19
|
+
}
|
|
20
|
+
if (name === "get_ui_ux_skills") {
|
|
21
|
+
const clientOrError = await clientFromArgs(args, defaultCredentials);
|
|
22
|
+
if ("content" in clientOrError) {
|
|
23
|
+
return toolJson({
|
|
24
|
+
...buildUiUxSkillsHandoffPayload(),
|
|
25
|
+
markdown: renderUiUxSkillsHandoffMarkdown(),
|
|
26
|
+
source: "static",
|
|
27
|
+
message: "Connect Majico MCP with project scope for DB-backed editable skills.",
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const { client } = clientOrError;
|
|
31
|
+
return toolJson(await client.cursorSkills.list());
|
|
32
|
+
}
|
|
33
|
+
if (name === "mcp_auth") {
|
|
34
|
+
return toolJson(buildMcpAuthRequiredPayload("connect_oauth"));
|
|
35
|
+
}
|
|
36
|
+
if ((name === "ping" || name === "health") &&
|
|
37
|
+
defaultCredentials?.planRequired) {
|
|
38
|
+
return toolJson({
|
|
39
|
+
ok: false,
|
|
40
|
+
...buildMcpAuthRequiredPayload("upgrade_plan"),
|
|
41
|
+
auth: defaultCredentials.auth ?? "oauth",
|
|
42
|
+
userId: defaultCredentials.userId ?? null,
|
|
43
|
+
projectId: defaultCredentials.projectId ?? null,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { CredentialSource } from "../credentials.js";
|
|
2
|
+
import { type ToolCallResult } from "./tool-call-helpers.js";
|
|
3
|
+
export declare function handleMajicoToolCall(name: string, args: Record<string, unknown> | undefined, defaultCredentials?: CredentialSource): Promise<ToolCallResult>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { buildMcpAuthRequiredPayload } from "../auth-prompt.js";
|
|
2
|
+
import { toolError, toolAuthRequired, clientFromArgs, presentContext, } from "./tool-call-helpers.js";
|
|
3
|
+
import { handlePreClientToolCall } from "./handle-tool-call-pre.js";
|
|
4
|
+
import { dispatchBrandingStudioTool } from "./dispatch-branding-studio.js";
|
|
5
|
+
import { dispatchPulseBlogTool } from "./dispatch-pulse-blog.js";
|
|
6
|
+
import { dispatchResearchAssetsTool } from "./dispatch-research-assets.js";
|
|
7
|
+
import { mcpSdkSurfaceError } from "../sdk-surface.js";
|
|
8
|
+
function isMajicoErrorLike(err) {
|
|
9
|
+
if (!err || typeof err !== "object")
|
|
10
|
+
return false;
|
|
11
|
+
const e = err;
|
|
12
|
+
return (e.name === "MajicoError" &&
|
|
13
|
+
(typeof e.status === "number" || typeof e.code === "string"));
|
|
14
|
+
}
|
|
15
|
+
export async function handleMajicoToolCall(name, args, defaultCredentials) {
|
|
16
|
+
try {
|
|
17
|
+
const pre = await handlePreClientToolCall(name, args, defaultCredentials);
|
|
18
|
+
if (pre)
|
|
19
|
+
return pre;
|
|
20
|
+
const clientOrError = await clientFromArgs(args, defaultCredentials);
|
|
21
|
+
if ("content" in clientOrError)
|
|
22
|
+
return clientOrError;
|
|
23
|
+
const { client, creds } = clientOrError;
|
|
24
|
+
const sdkError = mcpSdkSurfaceError(client);
|
|
25
|
+
if (sdkError)
|
|
26
|
+
return toolError(sdkError);
|
|
27
|
+
const ctx = presentContext(creds, defaultCredentials);
|
|
28
|
+
const branding = await dispatchBrandingStudioTool(name, args, client, creds, ctx, defaultCredentials);
|
|
29
|
+
if (branding)
|
|
30
|
+
return branding;
|
|
31
|
+
const pulseBlog = await dispatchPulseBlogTool(name, args, client);
|
|
32
|
+
if (pulseBlog)
|
|
33
|
+
return pulseBlog;
|
|
34
|
+
const research = await dispatchResearchAssetsTool(name, args, client);
|
|
35
|
+
if (research)
|
|
36
|
+
return research;
|
|
37
|
+
return toolError(`Unknown tool: ${name}`);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (isMajicoErrorLike(err)) {
|
|
41
|
+
if (err.code === "plan_required" || err.code === "INSUFFICIENT_TOKENS") {
|
|
42
|
+
return toolAuthRequired(buildMcpAuthRequiredPayload("upgrade_plan"));
|
|
43
|
+
}
|
|
44
|
+
if (err.body?.code === "INSUFFICIENT_TOKENS") {
|
|
45
|
+
return toolAuthRequired(buildMcpAuthRequiredPayload("upgrade_plan"));
|
|
46
|
+
}
|
|
47
|
+
if (err.code === "auth_invalid_key" ||
|
|
48
|
+
err.code === "auth_missing" ||
|
|
49
|
+
err.status === 401) {
|
|
50
|
+
return toolAuthRequired(buildMcpAuthRequiredPayload("connect_oauth"));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
54
|
+
return toolError(message.replace(/Bearer\s+\S+/gi, "Bearer [REDACTED]"));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { MajicoClient } from "@majico/sdk";
|
|
2
|
+
import { type CredentialSource, type ResolvedCredentials } from "../credentials.js";
|
|
3
|
+
import type { McpAuthRequiredPayload } from "../auth-prompt.js";
|
|
4
|
+
import type { McpContentBlock, PresentContext } from "../present-interactive.js";
|
|
5
|
+
export type ToolCallResult = {
|
|
6
|
+
content: McpContentBlock[];
|
|
7
|
+
isError?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function toolJson(data: unknown): ToolCallResult;
|
|
10
|
+
export declare function toolPresent(content: McpContentBlock[]): ToolCallResult;
|
|
11
|
+
export declare function requireStringArg(args: Record<string, unknown> | undefined, key: string): string | null;
|
|
12
|
+
/** Build stable markdown for local-contract brand scaffolding tests and handoff. */
|
|
13
|
+
export declare function buildStableBrandMarkdown(args: Record<string, unknown> | undefined): ToolCallResult;
|
|
14
|
+
export declare function presentContext(creds: ResolvedCredentials, defaults?: CredentialSource): PresentContext;
|
|
15
|
+
export declare function toolError(message: string): ToolCallResult;
|
|
16
|
+
export declare function toolAuthRequired(payload: McpAuthRequiredPayload): ToolCallResult;
|
|
17
|
+
type ClientContext = ToolCallResult | {
|
|
18
|
+
client: MajicoClient;
|
|
19
|
+
creds: ResolvedCredentials;
|
|
20
|
+
};
|
|
21
|
+
export declare function clientFromArgs(args: Record<string, unknown> | undefined, defaultCredentials?: CredentialSource): Promise<ClientContext>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { createClientFromCredentials, readEnvCredentials, resolveCredentials, } from "../credentials.js";
|
|
2
|
+
export function toolJson(data) {
|
|
3
|
+
return {
|
|
4
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export function toolPresent(content) {
|
|
8
|
+
return { content };
|
|
9
|
+
}
|
|
10
|
+
export function requireStringArg(args, key) {
|
|
11
|
+
const value = args?.[key];
|
|
12
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
13
|
+
}
|
|
14
|
+
/** Build stable markdown for local-contract brand scaffolding tests and handoff. */
|
|
15
|
+
export function buildStableBrandMarkdown(args) {
|
|
16
|
+
const productName = requireStringArg(args, "productName");
|
|
17
|
+
const positioningConcept = requireStringArg(args, "positioningConcept");
|
|
18
|
+
const audience = requireStringArg(args, "audience");
|
|
19
|
+
const tone = requireStringArg(args, "tone");
|
|
20
|
+
if (!productName || !positioningConcept || !audience || !tone) {
|
|
21
|
+
return toolError("productName, positioningConcept, audience, and tone are required.");
|
|
22
|
+
}
|
|
23
|
+
return toolJson({
|
|
24
|
+
productName,
|
|
25
|
+
sections: ["product_name", "positioning_concept", "audience", "tone"],
|
|
26
|
+
markdown: [
|
|
27
|
+
`# ${productName}`,
|
|
28
|
+
"",
|
|
29
|
+
"## Product Name",
|
|
30
|
+
productName,
|
|
31
|
+
"",
|
|
32
|
+
"## Positioning / Concept",
|
|
33
|
+
positioningConcept,
|
|
34
|
+
"",
|
|
35
|
+
"## Audience",
|
|
36
|
+
audience,
|
|
37
|
+
"",
|
|
38
|
+
"## Tone",
|
|
39
|
+
tone,
|
|
40
|
+
"",
|
|
41
|
+
].join("\n"),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export function presentContext(creds, defaults) {
|
|
45
|
+
const candidates = [
|
|
46
|
+
defaults?.publicBaseUrl?.trim(),
|
|
47
|
+
process.env.MAJICO_PUBLIC_BASE_URL?.trim(),
|
|
48
|
+
creds.baseUrl?.trim(),
|
|
49
|
+
"https://majico.xyz",
|
|
50
|
+
];
|
|
51
|
+
const publicBaseUrl = candidates.find((url) => {
|
|
52
|
+
if (!url)
|
|
53
|
+
return false;
|
|
54
|
+
try {
|
|
55
|
+
const host = new URL(url).hostname;
|
|
56
|
+
return host !== "0.0.0.0" && host !== "::" && host !== "[::]";
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}) ?? "https://majico.xyz";
|
|
62
|
+
return { projectId: creds.projectId, publicBaseUrl };
|
|
63
|
+
}
|
|
64
|
+
export function toolError(message) {
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
67
|
+
isError: true,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function toolAuthRequired(payload) {
|
|
71
|
+
return {
|
|
72
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
|
|
73
|
+
isError: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function credentialErrorResult(resolved) {
|
|
77
|
+
if ("authRequired" in resolved &&
|
|
78
|
+
resolved.authRequired &&
|
|
79
|
+
resolved.action &&
|
|
80
|
+
resolved.message) {
|
|
81
|
+
return toolAuthRequired({
|
|
82
|
+
authRequired: true,
|
|
83
|
+
action: resolved.action,
|
|
84
|
+
message: resolved.message,
|
|
85
|
+
agentInstructions: resolved.agentInstructions,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return toolError(resolved.error);
|
|
89
|
+
}
|
|
90
|
+
export function clientFromArgs(args, defaultCredentials) {
|
|
91
|
+
const envDefaults = {
|
|
92
|
+
...readEnvCredentials(),
|
|
93
|
+
...defaultCredentials,
|
|
94
|
+
};
|
|
95
|
+
return resolveCredentials({
|
|
96
|
+
projectId: args?.projectId,
|
|
97
|
+
apiKey: args?.apiKey,
|
|
98
|
+
baseUrl: defaultCredentials?.baseUrl,
|
|
99
|
+
}, envDefaults).then((resolved) => {
|
|
100
|
+
if ("error" in resolved)
|
|
101
|
+
return credentialErrorResult(resolved);
|
|
102
|
+
return { client: createClientFromCredentials(resolved), creds: resolved };
|
|
103
|
+
});
|
|
104
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
export declare const MAJICO_USER_TOOLS: Tool[];
|
|
3
|
+
/** Admin-only bootstrap tools — not listed unless X-Majico-Agent-Secret is present. */
|
|
4
|
+
export declare const MAJICO_ADMIN_BOOTSTRAP_TOOLS: Tool[];
|
|
5
|
+
/** Full tool catalog including admin bootstrap (documentation / stdio with agent env). */
|
|
6
|
+
export declare const MAJICO_TOOLS: Tool[];
|
|
7
|
+
/**
|
|
8
|
+
* Tools exposed on tools/list for a given MCP session.
|
|
9
|
+
* Bootstrap tools require admin agent secret — never shown to normal OAuth/API-key users.
|
|
10
|
+
*/
|
|
11
|
+
export declare function listMcpTools(options?: {
|
|
12
|
+
includeAdminTools?: boolean;
|
|
13
|
+
}): Tool[];
|
|
14
|
+
export { classifyMcpTool, MCP_LLM_TOOL_NAMES, partitionMcpToolNames, type McpToolKind, } from "./tool-matrix.js";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { MCP_AUTH_TOOL_DESCRIPTION, withBrandingAuthStep, } from "./constants.js";
|
|
2
|
+
import { BRANDING_TOOL_DEFINITIONS } from "./tool-definitions-branding.js";
|
|
3
|
+
import { STUDIO_PULSE_TOOL_DEFINITIONS } from "./tool-definitions-studio-pulse.js";
|
|
4
|
+
import { BLOG_GIT_TOOL_DEFINITIONS } from "./tool-definitions-blog-git.js";
|
|
5
|
+
import { RESEARCH_ALIAS_TOOL_DEFINITIONS } from "./tool-definitions-research-aliases.js";
|
|
6
|
+
const MAJICO_USER_TOOLS_RAW = [
|
|
7
|
+
...BRANDING_TOOL_DEFINITIONS,
|
|
8
|
+
...STUDIO_PULSE_TOOL_DEFINITIONS,
|
|
9
|
+
...BLOG_GIT_TOOL_DEFINITIONS,
|
|
10
|
+
...RESEARCH_ALIAS_TOOL_DEFINITIONS,
|
|
11
|
+
];
|
|
12
|
+
export const MAJICO_USER_TOOLS = [
|
|
13
|
+
{
|
|
14
|
+
name: "mcp_auth",
|
|
15
|
+
description: MCP_AUTH_TOOL_DESCRIPTION,
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
...MAJICO_USER_TOOLS_RAW.map(withBrandingAuthStep),
|
|
22
|
+
];
|
|
23
|
+
/** Admin-only bootstrap tools — not listed unless X-Majico-Agent-Secret is present. */
|
|
24
|
+
export const MAJICO_ADMIN_BOOTSTRAP_TOOLS = [
|
|
25
|
+
{
|
|
26
|
+
name: "bootstrap_project",
|
|
27
|
+
description: "Admin automation: create or reuse a project via Agent API (server MAJICO_AGENT_API_SECRET + X-Majico-Agent-Secret). Not for normal Cursor branding workflows.",
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
name: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Project display name, e.g. klaut.pro portal",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: ["name"],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
/** Full tool catalog including admin bootstrap (documentation / stdio with agent env). */
|
|
41
|
+
export const MAJICO_TOOLS = [
|
|
42
|
+
...MAJICO_USER_TOOLS,
|
|
43
|
+
...MAJICO_ADMIN_BOOTSTRAP_TOOLS,
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Tools exposed on tools/list for a given MCP session.
|
|
47
|
+
* Bootstrap tools require admin agent secret — never shown to normal OAuth/API-key users.
|
|
48
|
+
*/
|
|
49
|
+
export function listMcpTools(options) {
|
|
50
|
+
if (options?.includeAdminTools)
|
|
51
|
+
return MAJICO_TOOLS;
|
|
52
|
+
return MAJICO_USER_TOOLS;
|
|
53
|
+
}
|
|
54
|
+
export { classifyMcpTool, MCP_LLM_TOOL_NAMES, partitionMcpToolNames, } from "./tool-matrix.js";
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { ASK_USER_PROJECT_SCOPE, optionalCredentialProps, } from "./constants.js";
|
|
2
|
+
export const BLOG_GIT_TOOL_DEFINITIONS = [
|
|
3
|
+
{
|
|
4
|
+
name: "list_blog_posts",
|
|
5
|
+
description: "List SEO blog drafts for this project (slug, status, generation_status). Start here for blog workflow.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
...optionalCredentialProps,
|
|
10
|
+
limit: { type: "number", description: "Max posts (default 20)" },
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: "get_blog_post",
|
|
16
|
+
description: "Fetch one blog draft with outline, sections, dossier, and body_md when assembled.",
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
...optionalCredentialProps,
|
|
21
|
+
postId: { type: "string" },
|
|
22
|
+
},
|
|
23
|
+
required: ["postId"],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "get_blog_seo_handoff",
|
|
28
|
+
description: "SEO + implementation handoff for blog agents. Returns live SEO gate rules, MCP workflow, technical SEO (sitemap/robots/schema/OG/nginx), and optional per-post checklist. Call before drafting/implementing or when assemble fails the SEO gate.",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: {
|
|
32
|
+
...optionalCredentialProps,
|
|
33
|
+
postId: {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "Optional draft id — includes live score/checklist/fixes",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "suggest_blog_opportunities",
|
|
42
|
+
description: "Suggest research-backed SEO article ideas from project ICP + GTM context. First step for new articles.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: "object",
|
|
45
|
+
properties: { ...optionalCredentialProps },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "run_blog_research",
|
|
50
|
+
description: "Deep research + dossier for a blog concept (from suggest_blog_opportunities). Required before generate_blog_outline.",
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: "object",
|
|
53
|
+
properties: {
|
|
54
|
+
...optionalCredentialProps,
|
|
55
|
+
concept: {
|
|
56
|
+
type: "object",
|
|
57
|
+
description: "BlogConcept: id, question, primaryKeyword, workingTitle, pillar, intent",
|
|
58
|
+
},
|
|
59
|
+
articleType: { type: "string" },
|
|
60
|
+
postId: { type: "string", description: "Optional existing draft id" },
|
|
61
|
+
},
|
|
62
|
+
required: ["concept"],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "generate_blog_outline",
|
|
67
|
+
description: "Generate whole-article SEO outline from concept + dossier. Present sections; user must approve before drafting.",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
...optionalCredentialProps,
|
|
72
|
+
concept: { type: "object" },
|
|
73
|
+
dossier: { type: "object" },
|
|
74
|
+
articleType: { type: "string" },
|
|
75
|
+
postId: { type: "string" },
|
|
76
|
+
},
|
|
77
|
+
required: ["concept", "dossier"],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "approve_blog_outline",
|
|
82
|
+
description: "Approve outline gate (≥3 sections) before generate_blog_section. Call after user confirms outline.",
|
|
83
|
+
inputSchema: {
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: {
|
|
86
|
+
...optionalCredentialProps,
|
|
87
|
+
postId: { type: "string" },
|
|
88
|
+
},
|
|
89
|
+
required: ["postId"],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "generate_blog_section",
|
|
94
|
+
description: "Draft one section body (token-billed). Requires approved outline. Pass sectionId from outline.sections.",
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: "object",
|
|
97
|
+
properties: {
|
|
98
|
+
...optionalCredentialProps,
|
|
99
|
+
postId: { type: "string" },
|
|
100
|
+
sectionId: { type: "string" },
|
|
101
|
+
approve: {
|
|
102
|
+
type: "boolean",
|
|
103
|
+
description: "Mark section approved after user confirms text",
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
required: ["postId", "sectionId"],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "assemble_blog_post",
|
|
111
|
+
description: "Assemble approved sections into body_md + FAQ. Runs SEO gate unless skipSeoGate.",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
type: "object",
|
|
114
|
+
properties: {
|
|
115
|
+
...optionalCredentialProps,
|
|
116
|
+
postId: { type: "string" },
|
|
117
|
+
skipSeoGate: { type: "boolean" },
|
|
118
|
+
},
|
|
119
|
+
required: ["postId"],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "publish_blog_post",
|
|
124
|
+
description: "Publish assembled post. scope project (default) or platform (Creator required).",
|
|
125
|
+
inputSchema: {
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: {
|
|
128
|
+
...optionalCredentialProps,
|
|
129
|
+
postId: { type: "string" },
|
|
130
|
+
scope: { type: "string", enum: ["project", "platform"] },
|
|
131
|
+
force: { type: "boolean" },
|
|
132
|
+
},
|
|
133
|
+
required: ["postId"],
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "push_design_tokens_to_figma",
|
|
138
|
+
description: "Push compiled design tokens to Figma Variables (Enterprise + connected Figma account).",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
type: "object",
|
|
141
|
+
properties: {
|
|
142
|
+
...optionalCredentialProps,
|
|
143
|
+
fileKey: {
|
|
144
|
+
type: "string",
|
|
145
|
+
description: "Figma file key (or set projects.figma_variables_file_key)",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "sync_project_assets_to_figma",
|
|
152
|
+
description: "Incremental Figma sync — import new assets, update changed, skip unchanged. Returns REST results + MCP instructions for raster/markdown.",
|
|
153
|
+
inputSchema: {
|
|
154
|
+
type: "object",
|
|
155
|
+
properties: {
|
|
156
|
+
...optionalCredentialProps,
|
|
157
|
+
fileKey: {
|
|
158
|
+
type: "string",
|
|
159
|
+
description: "Figma file key (or set projects.figma_variables_file_key)",
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: "import_repo",
|
|
166
|
+
description: "Import brand context from a connected GitHub or GitLab repository into this project (enqueue repo_import)." +
|
|
167
|
+
ASK_USER_PROJECT_SCOPE,
|
|
168
|
+
inputSchema: {
|
|
169
|
+
type: "object",
|
|
170
|
+
properties: {
|
|
171
|
+
...optionalCredentialProps,
|
|
172
|
+
owner: { type: "string", description: "Repository owner or org" },
|
|
173
|
+
repo: { type: "string", description: "Repository name" },
|
|
174
|
+
ref: { type: "string", description: "Branch or ref (default main)" },
|
|
175
|
+
provider: { type: "string", enum: ["github", "gitlab"] },
|
|
176
|
+
},
|
|
177
|
+
required: ["owner", "repo"],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: "publish_landing_page",
|
|
182
|
+
description: "Publish htmlFrame landing content to Git (new repo, existing repo PR/MR, or org landing path).",
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: "object",
|
|
185
|
+
properties: {
|
|
186
|
+
...optionalCredentialProps,
|
|
187
|
+
target: {
|
|
188
|
+
type: "string",
|
|
189
|
+
enum: ["new_repo", "existing_repo", "org_landing"],
|
|
190
|
+
},
|
|
191
|
+
provider: { type: "string", enum: ["github", "gitlab"] },
|
|
192
|
+
elementId: {
|
|
193
|
+
type: "string",
|
|
194
|
+
description: "htmlFrame element id (defaults to first htmlFrame)",
|
|
195
|
+
},
|
|
196
|
+
html: {
|
|
197
|
+
type: "string",
|
|
198
|
+
description: "Optional HTML override (otherwise read from canvas)",
|
|
199
|
+
},
|
|
200
|
+
owner: { type: "string" },
|
|
201
|
+
repo: { type: "string" },
|
|
202
|
+
branch: { type: "string" },
|
|
203
|
+
orgLandingPath: { type: "string" },
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
];
|