feat: initial commit - Jhonny Editor
- Adicionado estrutura completa do projeto - Configurado MCP server para Premiere Pro - Adicionado documentação e skills - Configurado Gitignore para o projeto
This commit is contained in:
Executable
+273
@@ -0,0 +1,273 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { WORKFLOW_CATALOG, WORKFLOW_PROMPTS, WORKFLOW_RESOURCE } from "../src/workflows/catalog.js";
|
||||
import { annotationsForTool, structuredToolResult } from "../src/workflows/tool-metadata.js";
|
||||
import { createServer } from "../src/server.js";
|
||||
import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
|
||||
import type { Telemetry, TelemetryProperties } from "../src/telemetry.js";
|
||||
|
||||
describe("modern MCP surface", () => {
|
||||
it("publishes focused workflow prompts with inspection and verification guidance", () => {
|
||||
expect(WORKFLOW_PROMPTS).toHaveLength(WORKFLOW_CATALOG.length);
|
||||
expect(new Set(WORKFLOW_PROMPTS.map((prompt) => prompt.name)).size).toBe(WORKFLOW_PROMPTS.length);
|
||||
|
||||
const rendered = WORKFLOW_PROMPTS[0].render({ goal: "Create a 30 second teaser" });
|
||||
expect(rendered.messages[0].content.text).toContain("Begin with project inspection");
|
||||
expect(rendered.messages[0].content.text).toContain("inspect the result");
|
||||
});
|
||||
|
||||
it("exposes a machine-readable workflow resource", () => {
|
||||
const resource = JSON.parse(WORKFLOW_RESOURCE);
|
||||
expect(resource.version).toBe(1);
|
||||
expect(resource.workflows).toHaveLength(16);
|
||||
expect(resource.workflows[0].recommendedTools).toContain("get_premiere_state");
|
||||
const organization = resource.workflows.find((workflow: { id: string }) => workflow.id === "project-organization");
|
||||
expect(organization.recommendedTools).toContain("apply_editorial_organization_plan");
|
||||
expect(organization.recommendedTools).not.toContain("organize_project_items_uxp");
|
||||
expect(organization.summary).toContain("advanced/manual only");
|
||||
const transcriptFirst = resource.workflows.find((workflow: { id: string }) => workflow.id === "transcript-first-context");
|
||||
expect(transcriptFirst.recommendedTools).toContain("create_editorial_context_pack");
|
||||
});
|
||||
|
||||
it("marks inspection as read-only and script execution as open-world", () => {
|
||||
expect(annotationsForTool("get_project_info")).toMatchObject({
|
||||
readOnlyHint: true,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
});
|
||||
expect(annotationsForTool("delete_bin")).toMatchObject({
|
||||
readOnlyHint: false,
|
||||
destructiveHint: true,
|
||||
});
|
||||
expect(annotationsForTool("execute_extendscript").openWorldHint).toBe(true);
|
||||
expect(annotationsForTool("search_project_context")).toMatchObject({ readOnlyHint: true, idempotentHint: true });
|
||||
expect(annotationsForTool("create_context_edit_plan")).toMatchObject({ readOnlyHint: true, idempotentHint: true });
|
||||
expect(annotationsForTool("create_editorial_context_pack")).toMatchObject({ readOnlyHint: true, idempotentHint: true });
|
||||
expect(annotationsForTool("create_editorial_plan")).toMatchObject({ readOnlyHint: true, idempotentHint: true });
|
||||
expect(annotationsForTool("preview_editorial_plan")).toMatchObject({ readOnlyHint: true, idempotentHint: true });
|
||||
expect(annotationsForTool("verify_delivery_conformance")).toMatchObject({ readOnlyHint: true, idempotentHint: true, openWorldHint: false });
|
||||
expect(annotationsForTool("apply_editorial_organization_plan")).toMatchObject({
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
idempotentHint: false,
|
||||
});
|
||||
expect(annotationsForTool("manage_project_context")).toMatchObject({
|
||||
readOnlyHint: false,
|
||||
destructiveHint: true,
|
||||
idempotentHint: false,
|
||||
});
|
||||
for (const name of ["list_bins", "inspect_clip", "find_media", "check_project"]) {
|
||||
expect(annotationsForTool(name)).toMatchObject({ readOnlyHint: true, idempotentHint: true });
|
||||
}
|
||||
for (const name of ["remove_clip", "ripple_delete_clip", "close_project"]) {
|
||||
expect(annotationsForTool(name).destructiveHint).toBe(true);
|
||||
}
|
||||
expect(annotationsForTool("send_raw_script").openWorldHint).toBe(true);
|
||||
expect(annotationsForTool("save_project")).toMatchObject({
|
||||
title: "Save Project",
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
openWorldHint: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("builds stable structured result envelopes", () => {
|
||||
expect(structuredToolResult("ping", true, { ready: true })).toEqual({
|
||||
ok: true,
|
||||
tool: "ping",
|
||||
data: { ready: true },
|
||||
});
|
||||
expect(structuredToolResult("save_project", false, undefined, "offline")).toEqual({
|
||||
ok: false,
|
||||
tool: "save_project",
|
||||
error: "offline",
|
||||
});
|
||||
expect(structuredToolResult("ping", true)).toEqual({ ok: true, tool: "ping", data: null });
|
||||
expect(structuredToolResult("ping", false)).toEqual({ ok: false, tool: "ping", error: "Unknown error" });
|
||||
});
|
||||
|
||||
it("renders optional workflow constraints", () => {
|
||||
const rendered = WORKFLOW_PROMPTS[1].render({ goal: "clean dialogue", constraints: "preserve room tone" });
|
||||
expect(rendered.messages[0].content.text).toContain("Constraints: preserve room tone");
|
||||
});
|
||||
|
||||
it("advertises prompts, resources, and tool annotations over MCP", async () => {
|
||||
const server = createServer({ timeoutMs: 50 });
|
||||
const client = new Client({ name: "modernization-test", version: "1.0.0" });
|
||||
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
||||
|
||||
await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
||||
try {
|
||||
const prompts = await client.listPrompts();
|
||||
expect(prompts.prompts.map((prompt) => prompt.name)).toContain("premiere-rough-cut");
|
||||
|
||||
const resources = await client.listResources();
|
||||
expect(resources.resources.map((resource) => resource.uri)).toContain("config://premiere-workflows");
|
||||
expect(resources.resources.map((resource) => resource.uri)).toEqual(expect.arrayContaining([
|
||||
"premiere://effects/available",
|
||||
"premiere://effects/applied",
|
||||
"premiere://transitions/available",
|
||||
"premiere://export/presets",
|
||||
"premiere://project/metadata",
|
||||
]));
|
||||
expect(resources.resources.map((resource) => resource.uri)).toContain("config://premiere-project-context");
|
||||
expect(resources.resources.map((resource) => resource.uri)).toEqual(expect.arrayContaining([
|
||||
"premiere://project/info",
|
||||
"premiere://project/sequences",
|
||||
"premiere://project/media",
|
||||
"premiere://project/bins",
|
||||
"premiere://timeline/active",
|
||||
]));
|
||||
|
||||
const tools = await client.listTools();
|
||||
expect(tools.tools.find((tool) => tool.name === "get_project_info")?.annotations?.readOnlyHint).toBe(true);
|
||||
expect(tools.tools.map((tool) => tool.name)).toContain("get_capabilities");
|
||||
// The default profile grants inspect/edit/export/filesystem but not
|
||||
// unsafe-script, so the two scripting tools are not advertised.
|
||||
expect(tools.tools.map((tool) => tool.name)).not.toContain("execute_extendscript");
|
||||
expect(tools.tools.map((tool) => tool.name)).not.toContain("evaluate_expression");
|
||||
expect(tools.tools).toHaveLength(347);
|
||||
const capabilityTool = tools.tools.find((tool) => tool.name === "get_capabilities");
|
||||
expect(capabilityTool?.outputSchema).toMatchObject({
|
||||
type: "object",
|
||||
// MCP clients such as Claude Desktop can require the 2020-12 dialect.
|
||||
// Keep this explicit: an older SDK release silently serialized every
|
||||
// registered output schema as draft-07, making every tool unusable
|
||||
// before its handler could run.
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema",
|
||||
required: expect.arrayContaining(["ok", "tool"]),
|
||||
properties: expect.objectContaining({
|
||||
ok: expect.any(Object),
|
||||
tool: expect.any(Object),
|
||||
data: expect.any(Object),
|
||||
error: expect.any(Object),
|
||||
}),
|
||||
});
|
||||
expect(tools.tools.map((tool) => tool.name)).toEqual(expect.arrayContaining([
|
||||
"manage_project_context",
|
||||
"search_project_context",
|
||||
"create_context_edit_plan",
|
||||
"create_editorial_context_pack",
|
||||
"create_editorial_plan",
|
||||
"preview_editorial_plan",
|
||||
]));
|
||||
expect(tools.tools.find((tool) => tool.name === "create_editorial_context_pack")?.inputSchema)
|
||||
.toMatchObject({
|
||||
properties: {
|
||||
max_entries: { type: "integer", minimum: 1, maximum: 50 },
|
||||
max_characters: { type: "integer", minimum: 1024, maximum: 24_000 },
|
||||
},
|
||||
});
|
||||
expect(tools.tools.find((tool) => tool.name === "search_project_context")?.inputSchema)
|
||||
.toMatchObject({
|
||||
properties: { max_results: { type: "integer", minimum: 1, maximum: 50 } },
|
||||
});
|
||||
|
||||
const capabilities = await client.callTool({
|
||||
name: "get_capabilities",
|
||||
arguments: {},
|
||||
});
|
||||
const capabilityData = (capabilities.structuredContent as any).data;
|
||||
expect(capabilityData.tools.generatedFrom).toBe("registered-tool-catalog");
|
||||
// The catalog intentionally reports every tool that exists — including
|
||||
// ones this profile disables, each flagged with its authority state — so
|
||||
// it is a superset of what tools/list advertises.
|
||||
expect(capabilityData.tools.total).toBeGreaterThanOrEqual(tools.tools.length);
|
||||
expect(capabilityData.tools.tools.map((tool: any) => tool.name)).toEqual(
|
||||
expect.arrayContaining(tools.tools.map((tool) => tool.name)),
|
||||
);
|
||||
expect(
|
||||
capabilityData.tools.tools.find((tool: any) => tool.name === "create_editorial_context_pack"),
|
||||
).toMatchObject({
|
||||
backend: "local",
|
||||
authority: { required: "inspect", enabled: true },
|
||||
verificationBoundary: "static_metadata_only",
|
||||
hostVerificationRequired: false,
|
||||
});
|
||||
expect(
|
||||
capabilityData.tools.tools.find((tool: any) => tool.name === "execute_extendscript")
|
||||
?.authority,
|
||||
).toMatchObject({ required: "unsafe-script", enabled: false });
|
||||
} finally {
|
||||
await client.close();
|
||||
await server.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("narrows tools/list with an explicit workflow pack without changing the authority report", async () => {
|
||||
const server = createServer({ timeoutMs: 50 }, { toolPacks: "essential" });
|
||||
const client = new Client({ name: "tool-pack-test", version: "1.0.0" });
|
||||
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
||||
|
||||
await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
||||
try {
|
||||
const tools = await client.listTools();
|
||||
const names = tools.tools.map((tool) => tool.name);
|
||||
expect(names).toEqual(expect.arrayContaining([
|
||||
"ping",
|
||||
"get_capabilities",
|
||||
"get_project_info",
|
||||
"inspect_sequence_review_report",
|
||||
"preview_edit_plan",
|
||||
"verify_delivery_file",
|
||||
]));
|
||||
expect(names).not.toContain("create_bin");
|
||||
// Essential is a 14-tool focused path (including the two always-visible
|
||||
// diagnostics), versus 342 tools in the default full catalog.
|
||||
expect(names).toHaveLength(14);
|
||||
|
||||
const capabilities = await client.callTool({
|
||||
name: "get_capabilities",
|
||||
arguments: {},
|
||||
});
|
||||
const capabilityData = (capabilities.structuredContent as any).data;
|
||||
expect(capabilityData.toolPacks).toMatchObject({
|
||||
source: "explicit",
|
||||
selected: ["essential"],
|
||||
fullCatalog: false,
|
||||
});
|
||||
expect(capabilityData.authority.enabled).toEqual(expect.arrayContaining([
|
||||
"inspect",
|
||||
"edit",
|
||||
"export",
|
||||
"filesystem",
|
||||
]));
|
||||
} finally {
|
||||
await client.close();
|
||||
await server.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("records bounded tool usage without arguments or result content", async () => {
|
||||
const events: Array<{ event: string; properties?: TelemetryProperties }> = [];
|
||||
const telemetry: Telemetry = {
|
||||
enabled: true,
|
||||
capture: (event, properties) => events.push({ event, properties }),
|
||||
shutdown: async () => {},
|
||||
};
|
||||
const server = createServer({ timeoutMs: 50 }, { telemetry });
|
||||
const client = new Client({ name: "telemetry-test", version: "1.0.0" });
|
||||
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
||||
|
||||
await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
||||
try {
|
||||
await client.callTool({
|
||||
name: "get_capabilities",
|
||||
arguments: {},
|
||||
});
|
||||
|
||||
expect(events).toHaveLength(1);
|
||||
expect(events[0]).toMatchObject({
|
||||
event: "mcp_tool_call",
|
||||
properties: {
|
||||
tool: "get_capabilities",
|
||||
outcome: "succeeded",
|
||||
},
|
||||
});
|
||||
expect(events[0].properties).not.toHaveProperty("arguments");
|
||||
expect(events[0].properties).not.toHaveProperty("result");
|
||||
} finally {
|
||||
await client.close();
|
||||
await server.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user